Using a bucket script aggregation inside filter aggreagtion


(Gevorg) #1

Hi,

I am trying to use bucket_script aggregations inside a filter aggregation.

My query looks like this (I used count for simplicity in this example, but actual bucket script that I need is more complicated, so I do need a bucket_script)

"aggs": {
"filt": {
"filter": {
"bool": {
"should": [{
"match": {
"age": "24"
}}]
}
},
"aggs": {
"bucket_agg": {
"bucket_script": {
"buckets_path": {
"tc": "_count"
},
"script": "params.tc"
}
}
}
}
}

I get an error from elastic search saying

{
"error": {
"root_cause": [],
"type": "search_phase_execution_exception",
"reason": "",
"phase": "fetch",
"grouped": true,
"failed_shards": [],
"caused_by": {
"type": "class_cast_exception",
"reason": "org.elasticsearch.search.aggregations.bucket.filter.InternalFilter cannot be cast to org.elasticsearch.search.aggregations.InternalMultiBucketAggregation"
}
},
"status": 503
}

However, when I wrap up the bucket script aggregation inside another aggregation, terms aggregation for example, it works

Query

  "aggs": {
        "filt": {
          "filter": {
            "bool": {
              "should": [{
                "match": {
                  "age": "24"
                }}]
            }
          },
          "aggs": {
            "name": {
              "terms": {
                "field": "name"
              },
              "aggs": {
                "bucket_agg": {
                  "bucket_script": {
                    "buckets_path": {
                      "tc": "_count"
                    },
                    "script": "params.tc"
                  }
                }
              }
            }
          }
        }
      }

Is there a reason why a bucket directly under a filter is not supported and is there a way to work around this?

Thank you,
Gevorg


(Abdon Pijpelink) #2

The bucket_script aggregation operates on multi-bucket aggregations. The filter aggregation only creates a single bucket.

The workaround is to use a filters aggregation instead of a filter agg (note the extra "s" for the plural "filters"). Something like this should work:

{
  "aggs": {
    "filt": {
      "filters": {
        "filters": {
          "age_24": {
            "bool": {
              "should": [
                {
                  "match": {
                    "age": "24"
                  }
                }
              ]
            }
          }
        }
      },
      "aggs": {
        "bucket_agg": {
          "bucket_script": {
            "buckets_path": {
              "tc": "_count"
            },
            "script": "params.tc"
          }
        }
      }
    }
  }
}

(Gevorg) #3

That worked. Thank you!

But this raises another question for me. If the reason that filter doesn't work with bucket_script is that we have a multi-bucket aggregation, why does it work with terms aggregation? It is also a multi-bucket aggregation, isn't it?


(Abdon Pijpelink) #4

It is the other way around: both the terms as well as the filters aggregation are multi-bucket. It did not work with the filter aggregation because it is single-bucket.


(system) #5

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.