Search Autocomplete

A typical user expects to see results or suggestions immediately as she types a request, and hitting Enter button to see results is now considered a bad user experience. There are two typical approaches here: autocomplete and autosuggestion. I will review both, check the difference, and explain when you should use each one.

Solution

Dictionary

Every time user enters something in the search box, he may expect to see one of two things.

Suppose the application has a specific purpose, search results contain concrete results, and the user knows what she is looking for. In that case, it makes sense to show the first several results immediately. In such a case user can immediately pick one of them and do something with it. It is called autocomplete.

Autocomplete usually uses standard full-text search to retrieve data from the search index. Then application builds some visual representation for this data and shows it to the user. Autocomplete should be fast, so it is a good idea to check performance and feedback time. The user should see results as quickly as possible. Sometimes autocomplete may also show small images to build a better visual representation of the result set.

If the application is multipurpose and it is unclear what to show, then it is better to show typical search requests, so the user can pick one of them and then see results. In such a case user has to choose the correct search phrase first, open the search results page, and only then do something with results. It is called autosuggestion.

Unlike autocomplete, autosuggestion usually requires a separate field or even index. It is used to build possible combinations of words and phrases that may make sense for the user. Autosuggestion usually does not show results but possible requests other users typically perform. Performance recommendation affects autosuggestion as well because the user must not wait a lot.

Implementation

Typing on laptop

Autocomplete implementation is straightforward. It requires a typical full-text search query, and then the application has to render the results to the user. You may follow the Default Search Behaviour guide to implement such a solution.

Autosuggestion is much more interesting to work with. Elasticsearch offers many types of suggesters: term, phrase, context, and finally autocomplete. We are primarily interested in the last one as it implements what we need here.

As usual, we need to create an index together with mapping. The first field data is just an informational field, but the second field, called suggest, is where we will store suggestions for a document. Pay attention to the field type called completion. It tells Elasticsearch that this field will be used for autocomplete suggestions.

curl -X PUT "localhost:9200/autocomplete-suggestions" curl -X PUT "localhost:9200/autocomplete-suggestions" -H 'Content-Type: application/json' -d' { "mappings": { "properties": { "data": { "type": "text", "analyzer": "english" }, "suggest": { "type": "completion" } } } } '

Next, let us index a couple of documents without any suggestions for now.

curl -X PUT "localhost:9200/autocomplete-suggestions/_doc/1" -H 'Content-Type: application/json' -d' { "data": "Apple An apple is an edible fruit produced by an apple tree (Malus domestica). Apple trees are cultivated worldwide and are the most widely grown species in the genus Malus. fruit sweet red yellow" } ' curl -X PUT "localhost:9200/autocomplete-suggestions/_doc/2" -H 'Content-Type: application/json' -d' { "data": "Orange The orange is the fruit of various citrus species in the family Rutaceae (see list of plants known as orange); it primarily refers to Citrus × sinensis,[1] which is also called sweet orange, to distinguish it from the related Citrus × aurantium, referred to as bitter orange. fruit sour orange" } '

And now it is time to add suggestions to these documents. Following queries adds several suggestions to each of the documents that match the content of the document. Each suggestion may have a weight that is used to sort in the result set.

curl -X PUT "localhost:9200/autocomplete-suggestions/_doc/1?refresh" -H 'Content-Type: application/json' -d' { "suggest": [ { "input": "Apple", "weight": 10 }, { "input": "Fruit", "weight": 3 }, { "input": "Tree" }, { "input": "Red" }, { "input": "Yellow" } ] } ' curl -X PUT "localhost:9200/autocomplete-suggestions/_doc/2?refresh" -H 'Content-Type: application/json' -d' { "suggest": [ { "input": "Orange", "weight": 10 }, { "input": "Fruit", "weight": 3 }, { "input": "Tree" }, { "input": "Sour" } ] } '

Finally, let us try to find documents that match an appropriate request using autocomplete suggester. We must give it a name (e.g., autocomplete) and pass the request string as a prefix value.

curl -X POST "localhost:9200/autocomplete-suggestions/_search?pretty" -H 'Content-Type: application/json' -d' { "suggest": { "autocomplete": { "prefix": "fru", "completion": { "field": "suggest" } } } } '

And here are the results: both documents found and Elasticsearch returns both the suggestion phrase and related information about the found document.

{ "took" : 15, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 0, "relation" : "eq" }, "max_score" : null, "hits" : [ ] }, "suggest" : { "autocomplete" : [ { "text" : "fru", "offset" : 0, "length" : 3, "options" : [ { "text" : "Fruit", "_index" : "autocomplete-suggestions", "_type" : "_doc", "_id" : "1", "_score" : 3.0, "_source" : { "suggest" : [ { "input" : "Apple", "weight" : 10 }, { "input" : "Fruit", "weight" : 3 }, { "input" : "Tree" }, { "input" : "Red" }, { "input" : "Yellow" } ] } }, { "text" : "Fruit", "_index" : "autocomplete-suggestions", "_type" : "_doc", "_id" : "2", "_score" : 3.0, "_source" : { "suggest" : [ { "input" : "Orange", "weight" : 10 }, { "input" : "Fruit", "weight" : 3 }, { "input" : "Tree" }, { "input" : "Sour" } ] } } ] } ] } }

Previous lesson
<<
Error-tolerant Search

Next lesson
Boosting Search Results >>