Range aggregation with fixed buckets values


(Gustavo Orsi) #1

I need to create an aggregation, like "range" but I need to specify the "where" clause of each bucket.

For example if we aggregate on an "age" field, what range agg offer is:

  • bucket 1: to 10
  • bucket 2: from 10 to 50
  • bucket 3: from 50

what I need is:

  • bucket 1: [5,4334,211 and 76]
  • bucket 2: [66 and 435]
  • bucket 3: [5455, 7968, 1, 443 and 765]

(Think of the range of each bucket is a fixed list of ids, whichever doc that matches that id, put it into the bucket)

I don't want to create 3 "terms" aggregations with the "include" property, what I need is one aggregation with 3 buckets (just like range offers).

Any ideas or alternatives ?


(Colin Goodheart-Smithe) #2

You could use a filters aggregation for this. Each filter can be a bool or terms filter containing the values you want that bucket to match.

Hope that helps


(Gustavo Orsi) #3

So, we could have any arbitrary number of buckets. Think if each bucket holds the results from a "terms " aggregation from another type, that means that for a field with a high carnality we will end up with a high number or buckets which in turns means same number of filters.

We found another solution using "terms" aggregation with "script" where we can dynamically add params... what we don't know yet is which one is more performance.

"aggs": {
    "age_ranges": {
      "terms": {
        "script": {
          "inline": "if(ageMap.containsKey(doc['age'].value)){ageMap.get(doc['age'].value)} else {'<unmapped>'} ",
          "params": {
            "contentIdMapping": {
              "1": "bucket-3",
              "5": "bucket-1",
              "66": "bucket-2",
              "76": "bucket-1",
              "211": "bucket-1",
              "435": "bucket-2",
              "443": "bucket-3",
              "765": "bucket-3",
              "4334": "bucket-1",
              "5455": "bucket-3",
              "7968": "bucket-3"
            }
          }
        }
      }
    }

(system) #4