1
votes

I would like to create an index that contains a field called "home_city". I will need to perform a search on this index that returns all documents with a home_city field that is exactly "Little Rock". I will also need to perform a search on this index that returns all documents with a home_city field that contains any words with the query string as a prefix. For example, if the query string is "Ne", then documents with home_city = "New York" or home_city = "Long Neck" or home_city = "Nevinton" will be in the result.

I can create an index that allows either of these two queries, but not both.

For example, the former search (the exact full keyword search) works if I instruct the index to use Elastic's "keyword" analyzer. I specify this when creating the index like this...

PUT my_index
{
   "mappings":{
       "properties":{
          "home_city": {
             "type":"text",
             "analyzer":"keyword", 
         }
      }
   }
}

The following query correctly returns all documents with field home_city = "Little Rock"

{
  "query": {
    "bool": {
      "must": [
        {
              "query_string":{
                 "query":"Little Rock" 
           }
        }]
     }
   }
}

Also, as expected, if the query is not exactly "Little Rock", but rather "Little" or "Rock" then the response does not include documents with home_city="Little Rock". Good this is what we want.

The latter (prefix matching) search works if I create an index with default settings. The query looks like this...

{
  "query": {
            "match": {
                "home_city": "Di"
            }
      }
}

returns documents with field home_city = "San Diego" and documents with field home_city = "Diamondville".

However, I cannot get both of these queries to work on the same index. If I specify the keyword analyzer when creating the index, and execute the second query (the prefix matching query), then no documents match.

How can I create an index hat will work with queries that look for documents exactly matching the entire query string AND queries that look for documents containing the query as prefixes.

Ultimately, we are interested in replacing the prefix matching with a more sophisticated matching that includes prefix matching as well as other techniques. But for now, we would like to just figure out the problem described above.

Cheers.

1
are u still facing the issue - user156327

1 Answers

0
votes

You can map using fields

Mapping

{
   "mappings":{
       "properties":{
          "home_city": {
             "type":"text",      --> will store as tokens using standard analyzer
             "fields": {
               "keyword":{
                 "type":"keyword" --> will store entire text as single token
               }
             }
         }
      }
   }
}

Query 1:

GET index_10/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "query_string": {
            "query": "Little Rock"
          }
        }
      ]
    }
  }
}

Query 2: Use match_phrase_prefix instead of match_phrase

Match phrase 1. all the terms must appear 2. they must have the same order

Match_phrase_prefix

Returns documents that contain the words of a provided text, in the same order as provided. The last term of the provided text is treated as a prefix, matching any words that begin with that term.

GET index_10/_search
{
  "query": {
    "match_phrase_prefix": {
      "home_city": "di"
    }
  }
}

Points to consider

  1. If input by users it's better to use simple_query_string instead of query_string as it will not throw errors in case of bad search syntax .
  2. Match_phrase_prefix will only search in beginning of token. If requirement is to search anywhere in text , you can explore NGrams,EdgeNgrams and inbuilt autocomplete and search_as_you_type.