Filter aggregation

Filter aggregation #

A single-bucket aggregation that narrows the documents a nested aggregation runs on, with a query acting as the filter condition. Where the request’s query scopes everything, filter carves out one named sub-scope inside the aggregation tree — the aggregation equivalent of a WHERE clause.

How it works #

Every matching document is tested against the condition; those that pass form the bucket. The response is a single-bucket object carrying the filtered doc_count plus any nested aggregation results:

"hat_sales": { "doc_count": 30, "total": { "value": 900.0 } }

The condition is any one query clause in map form, and both the shorthand and Pizza’s normalized spelling are accepted:

  • term / match — equality: {"term": {"type": "hat"}} or {"term": {"field": "type", "value": "hat"}}
  • terms — any-of: {"terms": {"type": ["hat", "mug"]}}
  • range — numeric bounds gte / gt / lte / lt, e.g. {"range": {"price": {"gte": 20}}}
  • match_all — matches everything (the full parent scope)

Multi-valued fields match when ANY of their elements satisfies the equality. Conditions compose with the outer query: the filter only ever narrows the set it inherits, never widens it (for an escape from the query scope see global).

Examples #

Total amount of hat sales only — a WHERE scope on the SQL side:

POST /sales/_search
{
  "aggs": {
    "t_shirts": {
      "filter": { "term": { "field": "type", "value": "t-shirt" } },
      "aggs": {
        "avg_price": { "avg": { "field": "price" } }
      }
    }
  }
}

Use cases #

  • Scoped metrics. “Revenue for hats only” (SUM(amount) WHERE type = 'hat') without a second request or a query that hides the other documents from sibling aggregations.
  • KPI fractions. A match_all filter as denominator next to a narrowed filter as numerator — error rate, delivered share, gold-tier share — all inside one aggregation tree.
  • Conditional averages. Average price over a range-filtered slice (price >= 20) while the outer request still sees every sale.
  • Side-by-side scopes. Several filters at once — that shape is filters.

Parameters for filter #

  • <filter query>
    (Required, query) The filter condition — any single query clause in the map form, e.g. {"term": {...}}.
  • aggs
    (Required, object) Nested sub-aggregations, computed over only the matching documents.

For multiple named filters in one aggregation, see filters.

  • filters — many named filters side by side
  • global — the opposite move: escape the query scope
  • missing — scope to documents LACKING a field
  • Term-level queries — the clause forms accepted as conditions
Calendar October 6, 2026
Edit Edit this page