Thuta Learning
IntermediateData & Databasesbeginner

Aggregations — Metric and Bucket

What you'll walk away with

  • Explain the core ideas behind Aggregations — Metric and Bucket
  • Run the sample Elasticsearch query or code and verify its output
  • Apply the technique correctly to the Tutorial Platform and production scenarios

Build the mental model

Aggregations are Elasticsearch's analytics framework, shifting the question from "which documents match" (search) to "what patterns or summaries exist in the data" (analytics) — serving the same purpose as SQL's `GROUP BY` combined with `AVG()`/`COUNT()`. A metric aggregation (`avg`, `sum`, `min`, `max`, `stats`) takes a numeric field as input and returns one computed value (say, the average lesson count across all tutorials). A bucket aggregation (`terms`, `date_histogram`, `range`) groups documents into buckets by criteria — a `terms` aggregation builds one bucket per unique value of a `keyword` field and returns the document count in each, which is exactly why `terms` should run on a `keyword` or numeric field (running it on a `text` field creates one bucket per token/individual word, not the result you intended). Aggregations can be attached alongside a search query — the `query` first narrows the document set, and the aggregation then runs only over that narrowed set, so "filtered analytics" is achievable in a single request. Think of it like pulling both a pie chart (buckets = category counts) and an average score (a metric) out of survey data at the same time.

Connect it to a real scenario

On the Tutorial Platform's admin analytics dashboard, a chart answering "how many tutorials exist per topic" comes from a single `terms` bucket aggregation on the `tags` field — PostgreSQL would need a separate `GROUP BY tag` query, while Elasticsearch just attaches an `aggs` object next to the search query. Filter to "published in the last 30 days" and then run an `avg` aggregation over that narrowed set to also pull "average lesson count among recent tutorials" — search and analytics come back from a single request.

Try the working example

http
GET /tutorials/_search
{
  "size": 0,
  "query": {
    "range": { "publishedAt": { "gte": "now-30d" } }
  },
  "aggs": {
    "tutorials_per_tag": {
      "terms": { "field": "tags" }
    },
    "avg_lesson_count": {
      "avg": { "field": "lessonCount" }
    }
  }
}
You should see
You get per-tag document count buckets and the average lesson count, for tutorials published in the last 30 days.

5-minute try-it

Write a query combining a `terms` bucket aggregation on `difficulty` with a `max` metric aggregation on `lessonCount` in one request (use `size: 0`).

One important caution

Running a `terms` bucket aggregation on a `text` field (a field tokenized by an analyzer) — it creates a bucket per individual word, completely diverging from the intended category counts.

Wanting only aggregation results but leaving `size` at its default (10) — ten documents come back in the hits array anyway, needlessly bloating the response size and bandwidth; set `size: 0` instead.

Elasticsearch Guide — AggregationsElastic

Easy traps

  • Running a `terms` bucket aggregation on a `text` field (a field tokenized by an analyzer) — it creates a bucket per individual word, completely diverging from the intended category counts.
  • Wanting only aggregation results but leaving `size` at its default (10) — ten documents come back in the hits array anyway, needlessly bloating the response size and bandwidth; set `size: 0` instead.
  • Validate sample queries and requests on a local or test instance with recoverable data before applying them to production.

Exercise

Write a query combining a `terms` bucket aggregation on `difficulty` with a `max` metric aggregation on `lessonCount` in one request (use `size: 0`).

You'll know it worked when: You get per-tag document count buckets and the average lesson count, for tutorials published in the last 30 days.

Aggregations — Metric and Bucket | Thuta Learning