Bucket selector aggregation

Bucket selector aggregation #

A parent pipeline aggregation filtering the bucket list itself: a script predicate per bucket — buckets whose script evaluates false are dropped from the response. It is the HAVING clause of the aggregation world: the predicate sees computed metrics, not documents.

"big_days": {
  "bucket_selector": {
    "buckets_path": { "r": "revenue" },
    "script": "params.r > 150"
  }
}

How it works #

bucket_selector is declared inside the multi-bucket aggregation it decorates, next to the metrics it consumes. After the buckets are built, the engine resolves each named path against every bucket, evaluates the script once as a boolean, and removes the buckets that fail from the owning aggregation’s response. The selector itself never appears in the output — it is a filter, not a metric.

Details verified against the engine:

  • buckets_path follows the same rules as bucket_script: a map of variable names to sibling metric paths, a .value suffix, "_count" for document counts, or a plain string binding _value. Variables are reachable as params.r or bare r, and arrive as floats.
  • A gap (a named metric missing in that bucket) drops the bucket under the default skip policy; any other setting keeps it.
  • A script that fails at runtime keeps the bucket — a selector error never silently empties the response.
  • Truthiness of the result: a boolean is taken as-is; a number is true when non-zero; anything else (a string, an array) defaults to keep. Prefer explicit comparisons — params.r > 150 says what you mean.
  • Filtering happens on the finished bucket list, so a selector can reference any sibling metric of the same bucket — including a pipeline declared earlier in the same aggs object.
  • A second, engine-specific placement also works: declaring bucket_selector next to the bucket aggregation, with full parent>metric paths, returns the kept buckets as a standalone array instead of filtering the parent in place.

Examples #

Only the days whose single sale exceeded 150 survive; per_day comes back with just those buckets and no big_days entry anywhere. Compound predicates work too — let per = params.r / params.n; per > 50 && params.r > 1500 combines a derived ratio with a floor on the total (see pipeline scripts).

Use cases #

  • Threshold pruning — keep only buckets above a revenue, error or latency threshold, so the response a dashboard polls is already the interesting subset.
  • Breach isolation — over an SLA metric per bucket, select the breached ones; the empty result is itself the good news.
  • Noise-free comparisons — drop buckets with too little data (params.n < 5) before feeding the survivors to sibling pipelines or a client chart.
  • Top-tier focus — over customer-tier buckets, keep only the tiers a report covers.

Parameters for bucket_selector #

  • buckets_path
    (Required, object) Map of script variable names to sibling metric paths.
  • script
    (Required, string) Keep predicate over params.<name> (or the bare <name>) — see pipeline scripts.
  • gap_policy
    (Optional, string) skip (default) drops buckets with missing metrics; any other setting keeps them.
  • bucket_script — the same machinery producing a metric instead of a filter
  • bucket_sort — reordering and pagination of the bucket list (not yet active in this engine)
  • pipeline scripts — the script language reference
Calendar October 6, 2026
Edit Edit this page