# Autocomplete across multiple fields

**URL:** <https://discuss.elastic.co/t/autocomplete-across-multiple-fields/54604>\
**Category:** Elasticsearch\
**Created:** [July 4, 2016, 2:55am UTC](https://discuss.elastic.co/t/autocomplete-across-multiple-fields/54604 "2016-07-04T02:55:22Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![lessless](https://avatars.discourse-cdn.com/v4/letter/l/bc8723/32.png) [@lessless](https://discuss.elastic.co/u/lessless)\
**Post date:** [July 4, 2016, 2:55am UTC](https://discuss.elastic.co/t/autocomplete-across-multiple-fields/54604/1 "2016-07-04T02:55:22Z")

</div>

Hello,

I read about two search-as-you-type technics, one from "Definitive Guide" with edge-ngrams and another with Prefix Suggester at [https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html) which gave an initial overview of the ES autocomplete capabilities and shed light on one possible way to do that.

This is a typical address autocompletion, which involves 5 fields : `[Country, City, District, Ward, Street]`.  
For example full address might be `['Canada', 'Toronto', 'East York', 'Crescent Town', 'The Market Pl']` (almost made up for illustration purposes)  
Country field (for now) is excluded from the input, so query should be performed only across city, district, ward and street.  
User can start typing anything that he is thinking about (true random input generator in place!):  
`East York`  
`York`  
`Crescent`  
`Market Pl`  
etc.

What is the suggested approach to creating a robust and effective autocompletion solution in this situation?  
Should I combine all those fields into one and use edge-ngrams?

---

<div class="post-metadata">

**Author:** ![spinscale](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/spinscale/32/25011_2.png) [@spinscale](https://discuss.elastic.co/u/spinscale)\
**Post date:** [July 4, 2016, 7:24am UTC](https://discuss.elastic.co/t/autocomplete-across-multiple-fields/54604/2 "2016-07-04T07:24:45Z")

</div>

Hey,

if you use the completion suggester, there is no need for edge-ngrams - it is a prefix suggester however (please make sure that you understand the limitations of this!), so you need each of those as your own input. There are two strategies now. Either have an own suggester for each field and merge the results on the client side. Or take those five field contents and create a single suggester field, that returns a well normalized output.

You should try out both, however the latter one not requiring client side merging might be easier.

--Alex

---

<div class="post-metadata">

**Author:** ![lessless](https://avatars.discourse-cdn.com/v4/letter/l/bc8723/32.png) [@lessless](https://discuss.elastic.co/u/lessless)\
**Post date:** [July 8, 2016, 2:48am UTC](https://discuss.elastic.co/t/autocomplete-across-multiple-fields/54604/3 "2016-07-08T02:48:26Z")

</div>

Hello @spinscale!

I'm trying to put together completion suggester for all 4 address fields as it's described at [https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html)  
As far as I understood there are two limitations:

- it takes a time to build FST during document indexing
- terms will be looked up from the beginning of the field's value, so a user can type "Tor" to see "Toronto", but won't get anything for typing "onto"

From reading [https://www.elastic.co/blog/you-complete-me](https://www.elastic.co/blog/you-complete-me) I was able to derive only how to build autocompletion by combining all terms as inputs for the `address_suggest` field:

```auto
curl -X PUT localhost:9200/hotels/hotel/2 -d '
{
  "country": "Canada",
  "city": "Toronto",
  "district": "East York",
  "ward" : "Crescent Town",
   "street": "The Market Pl"
  "address_suggest": { 
    "input": [ 
     "Toronto",
     "East York",
     "Crescent Town",
      "The Market Pl"
    ],
    "output": "Toronto, East York, Crescent Town, The Market Pl"
  }
}'

```

Is it the only possible way? If there is another way and it's not too much, will really appreciate an example of a mapping and query examples.

Thanks.

---

<div class="post-metadata">

**Author:** ![spinscale](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/spinscale/32/25011_2.png) [@spinscale](https://discuss.elastic.co/u/spinscale)\
**Post date:** [July 8, 2016, 6:06am UTC](https://discuss.elastic.co/t/autocomplete-across-multiple-fields/54604/4 "2016-07-08T06:06:30Z")

</div>

Hey,

the other way I mentioned was, having dedicated `city_suggest`, `suburb_suggest`, `street_suggest` fields, querying all those three and combining the response manually. As you can see, this would be more work, so it might be easier to use what you already tried. Also, dont forget about the weights for scoring in your example 🙂

--Alex

---

<div class="post-metadata">

**Author:** ![lessless](https://avatars.discourse-cdn.com/v4/letter/l/bc8723/32.png) [@lessless](https://discuss.elastic.co/u/lessless)\
**Post date:** [July 16, 2016, 8:08am UTC](https://discuss.elastic.co/t/autocomplete-across-multiple-fields/54604/7 "2016-07-16T08:08:18Z")

</div>

Hey @spinscale, I simplified structure a little bit - now there is no `ward` and here is what I could came up with:

```auto
PUT /autocomplete
{
  "mappings": {
    "address" : {
      "properties" : {
        "city": { "type" : "string" },
        "district": { "type" : "string" },
        "street": { "type" : "string" },
        "city_suggest": {
          "type": "completion"
        },
        "district_suggest": {
          "type": "completion"
        },
        "street_suggest": {
          "type": "completion"
        }
      } 
    }
  }
}'

POST /autocomplete/address/1
{
  "city": "Kiev",
  "district": "Shevchenkovsky",
  "street": "Shevhenko",
  "city_suggest": {
    "input": ["Kiev"],
    "weight": "1"  
  },
  "district_suggest": {
      "input": ["Shevchenkovsky"],
      "output": "Kiev, Shevchenkovsky",
      "weight": 10
  },
  "street_suggest": {
      "input": ["Shevchenko"],
      "output": "Kiev, Shevchenkovsky, Shevchenko",
      "weight": 100
  }
}

POST /autocomplete/address/2
{
  "city": "Kiev",
  "district": "Shevchenkovsky",
  "street": "Pobedy ave",
   "city_suggest": {
    "input": ["Kiev"],
    "weight": "1"  
  },
  "district_suggest": {
      "input": ["Shevchenkovsky"],
      "output": "Kiev, Shevchenkovsky",
      "weight": 10
  },
  "street_suggest": {
      "input": ["Pobedy ave"],
      "output": "Kiev, Shevchenkovsky, Pobedy ave",
      "weight": 100
  }
}

```

Now, I had a hope to include `*_suggestion` in the `field` parameter of the query, but that yielded an error.

```auto
GET /autocomplete/_suggest
{
    "address": {
        "text" : "sh",
        "completion" : {
          "field" : ["city_suggest", "district_suggest", "street_suggest"]
        }
    }
}

```

In the end I wanted to see something like that

```auto
Kiev | Shevchenkovsky | Shevchenko 
Kiev | Shevchenkovsky

```

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [July 5, 2017, 10:35pm UTC](https://discuss.elastic.co/t/autocomplete-across-multiple-fields/54604/8 "2017-07-05T22:35:03Z")

</div>


