Elasticsearch: Use match query along with autocomplete

453 views Asked by At

I want to use match query along with autocomplete suggestion in ES5. Basically I want to restrict my autocomplete result based on an attribute, like autocomplete should return result within a city only.

MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("cityName", city);

SuggestBuilder suggestBuilder = new SuggestBuilder()
                    .addSuggestion("region", SuggestBuilders.completionSuggestion("region").text(text));

SearchResponse response = client.prepareSearch(index).setTypes(type)
                        .suggest(suggestBuilder)
                        .setQuery(queryBuilder)
                        .execute()
                        .actionGet();

The above doesn't seem to work correctly. I am getting both the results in the response both independent of each other.

Any suggestion?

1

There are 1 answers

0
LaserJesus On

It looks like the suggestion builder is creating a completion suggester. Completion suggesters are stored in a specialized structure that is separate from the main index, which means it has no access to your filter fields like cityName. To filter suggestions you need to explicitly define those same filter values when you create the suggestion, separate to the attributes you are indexing for the document to which the suggestion is attached. These suggester filters are called context. More information can be found in the docs.

The docs linked to above are going to explain this better than I can, but here is a short example. Using a mapping like the following:

"auto_suggest": {
   "type": "completion",
   "analyzer": "simple",
   "contexts": [
      { 
          "name": "cityName",
          "type": "category",
          "path": "cityName"
      }
    ]
}

This section of the index settings defines a completion suggester called auto_suggest with a cityName context that can be used to filter the suggestions. Note that the path value is set, which means this context filter gets its value from the cityName attribute in your main index. You can remove the path value if you want to explicitly set the context to something that isn't already in the main index.

To request suggestions while providing context, something like this in combination with the settings above should work:

"suggest": {
    "auto_complete":{
      "text":"Silv",
      "completion": {
         "field" : "auto_suggest",
         "size": 10,
         "fuzzy" : {
            "fuzziness" : 2
         },
         "contexts": {
            "cityName": [ "Los Angeles" ]
         }
      }
    }
  }

Note that this request also allows for fuzziness, to make it a little resilient to spelling mistakes. It also restricts the number of suggestions returned to 10.

It's also worth noting that in ES 5.x completion suggester are document centric, so if multiple documents have the same suggestion, you will receive duplicates of that suggestion if it matches the characters entered. There's an option in ES 6 to de-duplicate suggestions, but nothing similar in 5.x. Again it's best to think of completion suggesters existing in their own index, specifically an FST, which is explained in more detail here.