Elasticsearch completion suggester on multifield with different weighting

The Completion Suggester is actually pretty limited in term of scoring: you cannot do that. The only thing you can do is boost some entries but not the attributes inside an entry (see the weight options http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters-completion.html#indexing).

That's because the Completion Suggester doesn't do a "real search" -> it doesn't use the index. It's a simple "dictionary" designed to do "prefix" expansions faster than with an index + inverted lists.

You should give a try to Algolia -> the engine is designed to answer to prefix searches in realtime + having different "weights" per attribute. Here is a tutorial to implement auto-complete menu targeting several fields


As redox said, the completion suggester is really simple and doesn't support entries boosting. My solution would be to make two suggester fields, one for brand and one for product name:

POST /product_index
{
  "mappings": {
    "products": {
      "properties": {
        "brand": {
          "type": "string",
          "analyzer": "english"
        },
        "product_name": {
          "type": "string",
          "analyzer": "english"
        },
        "id": {
          "type": "long"
        },
        "lookup_count": {
          "type": "long"
        },
        "product-suggest": {
          "type": "completion",
          "analyzer": "simple",
          "payloads": true,
          "preserve_separators": true,
          "preserve_position_increments": true,
          "max_input_length": 50
        },
        "brand-suggest": {
          "type": "completion",
          "analyzer": "simple",
          "payloads": true,
          "preserve_separators": true,
          "preserve_position_increments": true,
          "max_input_length": 50
        },
        "upc": {
          "type": "string"
        }
      }
    }
  }
}

When indexing, fill both fields:

POST /product_index/products/2
{
  "id": 2,
  "brand": "Coca-Cola",
  "product_name": "Classic Coke",
  "brand-suggest": {
    "input": [
      "Coca-Cola"
    ],
    "output": "Classic Coke - Coca-Cola",
    "payload": {
      "id": 2,
      "product_name": "Classic Coke",
      "brand": "Coca-Cola",
      "popularity": 10
    }
  },
  "product-suggest": {
    "input": [
      "Classic Coke"
    ],
    "output": "Classic Coke - Coca-Cola",
    "payload": {
      "id": 2,
      "product_name": "Classic Coke",
      "brand": "Coca-Cola",
      "popularity": 10
    }
  }
}

When querying, make one suggest on both the brand and product suggesters:

POST /product_index/_search
{
    "suggest": {
      "product_suggestion": {
        "text": "coca-co",
        "completion": {
          "field": "product-suggest"
        }
      },
      "brand_suggestion": {
        "text": "coca-co",
        "completion": {
          "field": "brand-suggest"
        }
      }
    }
}

You can append the list of suggestions of brand-suggestion to the one of product suggestion, after having removed the duplicates, to have list of suggestions with only relevant suggestions, no duplicates and the product suggestions first.

Another solution would be to use a query with boosting on brand and product, instead of using suggesters. This implementation is however slower since it doesn't use suggesters.