Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

elasticsearch prefix query for multiple words to solve the autocomplete use case

How do I get elastic search to work to solve a simple autocomplete use case that has multiple words?

Lets say I have a document with the following title - Elastic search is a great search tool built on top of lucene.

So if I use the prefix query and construct it with the form -

{
    "prefix" : { "title" : "Elas" }
}

It will return that document in the result set.

However if I do a prefix search for

{
    "prefix" : { "title" : "Elastic sea" }
}

I get no results.

What sort of query do I need to construct so as to present to the user that result for a simple autocomplete use case.

like image 834
user1796571 Avatar asked Jul 17 '13 01:07

user1796571


2 Answers

A prefix query made on Elastic sea would match a term like Elastic search in the index, but that doesn't appear in your index if you tokenize on whitespaces. What you have is elastic and search as two different tokens. Have a look at the analyze api to find out how you are actually indexing your text.

Using a boolean query like in your answer you wouldn't take into account the position of the terms. You would get as a result the following document for example:

Elastic model is a framework to store your Moose object and search through them.

For auto-complete purposes you might want to make a phrase query and use the last term as a prefix. That's available out of the box using the match_phrase_prefix type in a match query, which was made available exactly for your usecase:

{
    "match" : {
        "message" : {
            "query" : "elastic sea",
            "type" : "phrase_prefix"
        }
    }
}

With this query your example document would match but mine wouldn't since elastic is not close to search there.

like image 140
javanna Avatar answered Oct 23 '22 11:10

javanna


To achieve that result, you will need to use a Boolean query. The partial word needs to be a prefix query and the complete word or phrase needs to be in a match clause. There are other tweaks available to the query like must should etc.. that can be applied as needed.

{
    "query": {
        "bool": {
            "must": [
                {
                    "prefix": {
                        "name": "sea"
                    }
                },
                {
                    "match": {
                        "name": "elastic"
                    }
                }
            ]
        }
    }
}
like image 41
user1796571 Avatar answered Oct 23 '22 11:10

user1796571