Faceted navigation, dashboards and log analytics are all aggregations over search results.
Aggregations summarise the documents matched by the query, in the same request. Set "size": 0 when you only need the summary, not the hits.
- Metric aggregations compute numbers:
avg,sum,min,max,stats,percentiles,cardinality(approximate distinct count using HyperLogLog++). - Bucket aggregations group documents:
terms(top values of a keyword field),range,histogram,date_histogram(calendar_interval: "day"orfixed_interval: "5m"),filters. - Sub-aggregations nest inside buckets: average price per category, errors per host per hour.
- Pipeline aggregations work on other aggregations' output:
derivative,cumulative_sum,bucket_sort.
Aggregations run on doc values, the columnar on-disk structure that keyword, numeric and date fields have by default. That's why you aggregate on category (keyword) or category.keyword, not on a text field, which errors by default.
Know the approximations: terms gathers the top terms from each shard and merges them, so counts can be slightly off with many shards (doc_count_error_upper_bound reports the bound, and shard_size trades work for accuracy). cardinality is approximate with a tunable precision_threshold. For paging through every combination of buckets, use the composite aggregation instead of a huge terms size.
Facets on an e-commerce page are typically a terms aggregation per attribute, with the user's selections applied through post_filter so the facets still show other options.
Example
GET /orders/_search
{
"size": 0,
"query": { "range": { "placed_at": { "gte": "now-30d/d" } } },
"aggs": {
"per_day": {
"date_histogram": { "field": "placed_at", "calendar_interval": "day" },
"aggs": { "revenue": { "sum": { "field": "total" } } }
},
"by_status": { "terms": { "field": "status", "size": 5 } },
"customers": { "cardinality": { "field": "customer.raw" } },
"order_value": { "percentiles": { "field": "total", "percents": [50, 95] } }
}
}
# "aggregations": {
# "by_status": { "buckets": [ { "key": "paid", "doc_count": 812 }, ... ] },
# "customers": { "value": 431 },
# "order_value": { "values": { "50.0": 38.5, "95.0": 212.0 } }, ... }Remember
- Metric aggs compute values; bucket aggs group; sub-aggs nest
- size: 0 when you only want aggregations
- Aggregate on keyword/numeric/date fields (doc values), not text
- terms and cardinality are approximate across shards
Watch out for
- Running a terms aggregation with size: 100000 to list everything; use composite and page through it.