11

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.

javanna
  • 59,145
  • 14
  • 144
  • 125
user1796571
  • 662
  • 2
  • 9
  • 21

2 Answers2

18

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.

javanna
  • 59,145
  • 14
  • 144
  • 125
  • I should have clarified and this is my mistake. The position of the terms is not important to me since I am only looking at titles and not against the entire description. Will the phrase_prefix query not bring back results if i searched for Elastic Moos in your example? – user1796571 Jul 18 '13 at 22:01
  • No it won't! The query I proposed takes into account the position of the terms and expands only the last one treating it as a prefix. – javanna Jul 19 '13 at 07:59
6

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"
                    }
                }
            ]
        }
    }
}
user1796571
  • 662
  • 2
  • 9
  • 21