Elasticsearch Aggregations

Aggregations let you analyze data instead of just searching it. They power dashboards, charts, and reports — answering questions like "how many products per category?" or "what is the average order value this month?"

Search vs Aggregation

Search:         "Find all products with name matching headphones"
                → Returns a list of matching documents

Aggregation:    "How many products exist per category?"
                → Returns summarized numbers, not documents

Both can run together in a single request.

Three Types of Aggregations

TypeWhat It DoesExample Output
MetricCalculates a number from field valuesAverage price: 1,499
BucketGroups documents into bucketsElectronics: 42 docs, Clothing: 18 docs
PipelineRuns calculations on other aggregation resultsMonth with highest average order value

Metric Aggregations

Metric aggregations compute values like sum, average, min, max, and count.

GET /products/_search
{
  "size": 0,
  "aggs": {
    "average_price": { "avg":   { "field": "price" } },
    "max_price":     { "max":   { "field": "price" } },
    "min_price":     { "min":   { "field": "price" } },
    "total_revenue": { "sum":   { "field": "price" } },
    "product_count": { "value_count": { "field": "price" } }
  }
}

size: 0 tells Elasticsearch not to return individual documents — only the aggregation results.

Response:

"aggregations": {
  "average_price": { "value": 1249.5  },
  "max_price":     { "value": 85000   },
  "min_price":     { "value": 99      },
  "total_revenue": { "value": 4850000 },
  "product_count": { "value": 3880    }
}

Bucket Aggregation: terms

Groups documents by a field's unique values — like a GROUP BY in SQL.

GET /products/_search
{
  "size": 0,
  "aggs": {
    "by_category": {
      "terms": {
        "field": "category",
        "size": 10
      }
    }
  }
}
"buckets": [
  { "key": "electronics", "doc_count": 420 },
  { "key": "clothing",    "doc_count": 310 },
  { "key": "books",       "doc_count": 198 }
]

Bucket Aggregation: range

Groups products into price bands — like a price filter on a shopping site:

GET /products/_search
{
  "size": 0,
  "aggs": {
    "price_ranges": {
      "range": {
        "field": "price",
        "ranges": [
          { "key": "Budget",   "to": 1000             },
          { "key": "Mid",      "from": 1000, "to": 5000 },
          { "key": "Premium",  "from": 5000            }
        ]
      }
    }
  }
}
"buckets": [
  { "key": "Budget",  "doc_count": 240 },
  { "key": "Mid",     "doc_count": 580 },
  { "key": "Premium", "doc_count": 92  }
]

Bucket Aggregation: date_histogram

Groups documents by time intervals — one bucket per month, week, or day.

GET /orders/_search
{
  "size": 0,
  "aggs": {
    "orders_per_month": {
      "date_histogram": {
        "field": "order_date",
        "calendar_interval": "month"
      }
    }
  }
}
Monthly order trend (diagram):

Jan  ██████ 60
Feb  ████████ 80
Mar  ████████████ 120
Apr  ██████████ 100

Nested Aggregations — Combining Bucket and Metric

Run a metric aggregation inside each bucket to get stats per group — like average price per category:

GET /products/_search
{
  "size": 0,
  "aggs": {
    "by_category": {
      "terms": { "field": "category" },
      "aggs": {
        "avg_price": { "avg": { "field": "price" } }
      }
    }
  }
}
"buckets": [
  {
    "key": "electronics",
    "doc_count": 420,
    "avg_price": { "value": 8450.00 }
  },
  {
    "key": "books",
    "doc_count": 198,
    "avg_price": { "value": 349.50 }
  }
]

Combining Search and Aggregation

Run a query and aggregation together in one request. The aggregation applies only to the documents matching the query:

GET /products/_search
{
  "query": {
    "term": { "in_stock": true }
  },
  "size": 0,
  "aggs": {
    "avg_price_in_stock": {
      "avg": { "field": "price" }
    }
  }
}

This returns the average price of only in-stock products — not everything in the index.

stats Aggregation — All Metrics in One Shot

"stats": { "field": "price" }

Response:
{
  "count": 3880,
  "min": 99,
  "max": 85000,
  "avg": 1249.5,
  "sum": 4849860
}

One query returns count, min, max, average, and sum simultaneously — saves multiple round trips.

Leave a Comment