Description
When a GROUP BY query uses COUNT(field) (not COUNT(*)) without an alias and references it in a HAVING clause, the bucket_selector's buckets_path maps the metric name to itself instead of the actual Elasticsearch aggregation name.
Root Cause
In extractMetricsPathForBucket (bridge/…/ElasticAggregation.scala), when the lookup matches via agg.field == metricName, the return value metricName -> metricName is incorrect because:
metricName = "field_name" (from Identifier.metricName)
aggName (local) = "count_field_name" (from s"${aggType}_${sourceField}")
- The bucket_selector gets
{"field_name": "field_name"} but the actual ES aggregation is named "count_field_name"
The correct return should map metricName to the local aggregation name (last segment of ElasticAggregation.aggName).
Complexity
The fix is non-trivial because ElasticAggregation.aggName in the case class stores the full nested path (e.g., "inner_products.filtered_agg.min_price"), not just the local name. Extracting the local name requires splitting on . which may be fragile. A cleaner approach would be to store the local aggregation name as a separate field in the case class.
Workaround
Always provide an alias for aggregations used in HAVING:
HAVING COUNT(field) > 5 -- broken
HAVING cnt > 5 -- works (with COUNT(field) AS cnt in SELECT)
Related
Description
When a
GROUP BYquery usesCOUNT(field)(notCOUNT(*)) without an alias and references it in aHAVINGclause, thebucket_selector'sbuckets_pathmaps the metric name to itself instead of the actual Elasticsearch aggregation name.Root Cause
In
extractMetricsPathForBucket(bridge/…/ElasticAggregation.scala), when the lookup matches viaagg.field == metricName, the return valuemetricName -> metricNameis incorrect because:metricName="field_name"(fromIdentifier.metricName)aggName(local) ="count_field_name"(froms"${aggType}_${sourceField}"){"field_name": "field_name"}but the actual ES aggregation is named"count_field_name"The correct return should map
metricNameto the local aggregation name (last segment ofElasticAggregation.aggName).Complexity
The fix is non-trivial because
ElasticAggregation.aggNamein the case class stores the full nested path (e.g.,"inner_products.filtered_agg.min_price"), not just the local name. Extracting the local name requires splitting on.which may be fragile. A cleaner approach would be to store the local aggregation name as a separate field in the case class.Workaround
Always provide an alias for aggregations used in
HAVING:Related
aggNamecomputation)