elasticsearchsearch-suggestionelastic-cloud

Elastic Search autocomplete/ partial matching for combines fields


I have my data in vehicle index:

{
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "@version": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "engine": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "make": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "model": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "year": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}

I'm working on search functionality where users can search with auto-suggestions sourced from ElasticSearch. Presently I'm using the following query:

{
  "query": {
    "multi_match": {
      "query" : "2014 Iko",
      "fields": [
        "make",
        "model",
        "year",
        "engine"
        ],
      "operator": "and"
    }
  }
}

With the above query I'm able to search results if I type the whole word. For e.g. If a user searches for Ford Mustang, it returns all the possible results (year and engine variations) for a combination of make as Ford and Mustang as model. Problem: The problem is when a user searches for "Ford Musta", elastic search results with 0 results. In this case I want to have all the options with Ford as make and Musta as phrase of model, year or engine.

The search can be in any order, so we want to support user searching for Mustang Ford and other possible orders.

Thanks a lot!!


Solution

  • If you want to use autocomplete, you cant use keyword. You need to use different mappings (=> es need to index data in a different way).

    I joins mappings if you want to use autocomplete on "model" and "engine". Add others fields if needed, or keep them as keyword.

    Note: This will obviously take more ressource on your es cluster. Note2: you will have to reindex your data, take a look at _reindex feature, please ask us if you have any question.

    {
                'settings': {
                    "analysis":{
                          "filter":{
                             "name_ngrams":{
                                "max_gram":"20",
                                "type":"edge_ngram",
                                "min_gram":"1",
                                "side":"front"
                             }
                          },
                          "analyzer":{
                             "partial_name":{
                                "type":"custom",
                                "filter":[
                                   "lowercase",
                                   "name_ngrams",
                                   "asciifolding"
                                ],
                                "tokenizer":"standard"
                             },
                             "full_name":{
                                "type":"custom",
                                "filter":[
                                   "lowercase",
                                   "asciifolding"
                                ],
                                "tokenizer":"standard"
                             }
                          }
                      }
                   },
                   "mappings":{
                         "properties":{
                            "model":{
                                 "type":"text",
                                 "analyzer":"partial_name",
                                 "search_analyzer":"full_name"
                             },
                            "engine":{
                               "type":"text",
                               "analyzer":"partial_name",
                               "search_analyzer":"full_name"
                            }
                         }
                   }
            }