Johan Hirsch
Johan Hirsch

Reputation: 577

Elasticsearch autocomplete integer field

I am trying to implement an autocomplete feature on a numeric field (it's actual type in ES is long).

I am using a jQuery UI Autocomplete widget on the client side, having it's source function send a query to Elasticsearch with the prefix term to get a number (say, 5) of autocomplete options.

The query I am using is something like the following:

{
    "size": 0,
    "query": {
        "prefix": {
            "myField": "<term>"
        }
    },
    "aggs": {
        "myAggregation": {
            "terms": { 
                "field": "myField",
                "size": 5
            }
        }
    }
}

Such that if myField has the distinct values: [1, 15, 151, 21, 22], and term is 1, then I'd expect to get from ES the buckets with keys [1, 15, 151].

The problem is this does not seem to work with numeric fields. For the above example, I am getting a single bucket with the key 1, and if term is 15 I am getting a single bucket with key 15, i.e. it only returns exact matches. In contrast, it works perfectly for string typed fields.

I am guessing I need some special mapping for myField, but I'd prefer to have the mapping as general as possible, while having the autocomplete working with minimal changes to the mapping (just to note - the index I am querying might be a general one, external to my application, so I will be able to change the type/field mappings in it only if the new mapping is something general and standard).

What are my options here?

Upvotes: 1

Views: 812

Answers (1)

Val
Val

Reputation: 217514

What I would do is to create a string sub-field into your integer field, like this:

{
    "myField": {
        "type": "integer",
        "fields": {
            "to_string": {
                "type": "string",
                "index": "not_analyzed"
            }
        }
    }
}

Then your query would need to be changed to the one below, i.e. query on the string field, but retrieve the terms aggregations from the integer field

{
  "size": 0,
  "query": {
    "prefix": {
      "myField.to_string": "1"
    }
  },
  "aggs": {
    "myAggregation": {
      "terms": {
        "field": "myField",
        "size": 5
      }
    }
  }
}

Note that you can also create a completely independent field, not necessary a sub-field, the key point is that one field needs the integer value to run the terms aggregation on and the other field needs the string value to run the prefix query on.

Upvotes: 2

Related Questions