Elasticsearch 聚合分析(Aggregations) 是其最强大的功能之一,远超传统数据库的 GROUP BY。它支持多维分析、嵌套聚合、管道聚合、统计计算等,广泛应用于数据分析、报表生成、搜索结果筛选(Facets)、监控系统等场景。
本文将全面详解 Aggregations 的类型、语法、使用场景与最佳实践。
一、什么是聚合(Aggregations)?
聚合(Aggregations) 是对搜索结果集进行 分组、统计、分析 的操作,返回结构化分析结果,而非原始文档。
✅ 类比 SQL:
SELECT category, COUNT(*), AVG(price) FROM products GROUP BY category HAVING COUNT(*) > 10;在 Elasticsearch 中通过
aggs实现。
二、聚合的基本结构
GET /index/_search
{
"query": { ... }, // 先过滤数据
"aggs": {
"NAME": { // 聚合名称(自定义)
"AGG_TYPE": { // 聚合类型(如 terms, avg)
... // 聚合参数
}
}
}
}
- 聚合基于 查询结果集 执行;
- 可嵌套、可组合;
- 不影响
_source返回的文档。
三、四大类聚合详解
Elasticsearch 聚合分为四类:
| 类型 | 说明 | 示例 |
|---|---|---|
| Metrics Aggregations | 计算数值指标(如平均值、总和) | avg, sum, stats |
| Bucket Aggregations | 分组(如按品牌、价格段分组) | terms, range, date_histogram |
| Pipeline Aggregations | 对其他聚合结果再计算 | derivative, moving_avg |
| Matrix Aggregations | 跨字段矩阵分析(实验性) | matrix_stats |
四、Metrics 聚合(指标聚合)
计算数值字段的统计信息。
1. avg / sum / min / max / value_count
"aggs": {
"avg_price": { "avg": { "field": "price" } },
"total_sales": { "sum": { "field": "sales_count" } },
"min_price": { "min": { "field": "price" } },
"doc_count": { "value_count": { "field": "title" } }
}
2. stats —— 一次性返回多个统计值
"aggs": {
"price_stats": {
"stats": { "field": "price" }
}
}
返回:
{
"count": 100,
"min": 100.0,
"max": 999.0,
"avg": 450.0,
"sum": 45000.0
}
3. extended_stats —— 扩展统计
包含方差、标准差等:
"aggs": {
"price_extended": {
"extended_stats": { "field": "price" }
}
}
返回 std_deviation, variance, sum_of_squares 等。
4. percentiles —— 百分位数
用于分析延迟、响应时间分布:
"aggs": {
"load_time_percentiles": {
"percentiles": {
"field": "load_time_ms",
"percents": [50, 95, 99, 99.9]
}
}
}
返回 P50、P95、P99 等。
5. cardinality —— 去重计数(HyperLogLog)
估算唯一值数量,性能高:
"aggs": {
"unique_users": {
"cardinality": { "field": "user_id" }
}
}
用于 UV 统计,误差率约 5%。
五、Bucket 聚合(桶聚合)
将文档分组到“桶”(Bucket)中,每个桶代表一组文档。
1. terms —— 按字段值分组(最常用)
"aggs": {
"by_brand": {
"terms": {
"field": "brand",
"size": 10,
"order": { "_count": "desc" }
}
}
}
- 适用于
keyword、ip、long等字段; size控制返回桶数量;- 默认按文档数排序。
⚠️ 不适用于
text字段(需开启fielddata,不推荐)。
2. range —— 范围分组
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 100000 }, // < 1000元
{ "from": 100000, "to": 500000 },
{ "from": 500000 }
]
}
}
}
3. date_histogram —— 时间直方图(最常用)
按时间间隔(如每小时、每天)分组。
"aggs": {
"sales_per_day": {
"date_histogram": {
"field": "created_at",
"calendar_interval": "day",
"time_zone": "Asia/Shanghai"
},
"aggs": {
"daily_revenue": { "sum": { "field": "price" } }
}
}
}
calendar_interval:second,minute,hour,day,week,month,quarter,year- 支持嵌套聚合(如每日销售额)
4. histogram —— 数值直方图
按固定间隔对数值分组:
"aggs": {
"price_histogram": {
"histogram": {
"field": "price",
"interval": 100000 // 每 1000 元一个桶
}
}
}
5. filters —— 自定义条件分组
"aggs": {
"category_stats": {
"filters": {
"filters": {
"electronics": { "term": { "category": "electronics" } },
"clothing": { "term": { "category": "clothing" } },
"high_price": { "range": { "price": { "gte": 500000 } } }
}
}
}
}
6. significant_terms —— 显著项分析
找出与整体分布相比“显著不同”的项,用于异常检测。
"aggs": {
"significant_brands": {
"significant_terms": {
"field": "brand"
}
}
}
示例:在“手机”类目中,“Apple” 出现频率远高于其他类目。
六、嵌套聚合(Nested Aggregations)
聚合可以嵌套,实现多维分析。
示例:按品牌分组,再统计价格分布
"aggs": {
"by_brand": {
"terms": { "field": "brand" },
"aggs": {
"price_stats": { "stats": { "field": "price" } },
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{ "to": 500000 },
{ "from": 500000 }
]
}
}
}
}
}
返回:
"buckets": [
{
"key": "Apple",
"doc_count": 15,
"price_stats": { "avg": 899900, ... },
"price_ranges": { "buckets": [...] }
}
]
七、Pipeline 聚合(管道聚合)
对其他聚合的结果进行二次计算。
1. derivative —— 导数(变化量)
"aggs": {
"sales_per_day": {
"date_histogram": { "field": "created_at", "calendar_interval": "day" },
"aggs": {
"daily_revenue": { "sum": { "field": "price" } },
"revenue_change": { "derivative": { "buckets_path": "daily_revenue" } }
}
}
}
返回每天相比前一天的收入变化。
2. moving_avg —— 移动平均
"revenue_ma": {
"moving_avg": {
"buckets_path": "daily_revenue",
"window": 7,
"model": "holt_winters"
}
}
用于趋势平滑。
3. bucket_script —— 自定义脚本计算
"profit_rate": {
"bucket_script": {
"buckets_path": {
"revenue": "daily_revenue",
"cost": "daily_cost"
},
"script": "params.revenue > 0 ? (params.revenue - params.cost) / params.revenue : 0"
}
}
八、聚合性能优化建议 ✅
| 场景 | 建议 |
|---|---|
terms 聚合 | 使用 keyword 字段,避免 text |
| 大基数字段 | 启用 execution_hint: "map" 或 "global_ordinals" |
| 深度嵌套 | 避免过深,影响性能 |
cardinality | 接受一定误差,性能远高于 terms + size=10000 |
date_histogram | 使用 fixed_interval 而非 calendar_interval(更高效) |
| 分页聚合 | 使用 composite 聚合支持深度分页 |
九、Composite Aggregation(复合聚合)
用于深度分页和大规模聚合。
"aggs": {
"my_buckets": {
"composite": {
"sources": [
{ "brand": { "terms": { "field": "brand" } } },
{ "category": { "terms": { "field": "category" } } }
],
"size": 10
}
}
}
支持 after 分页:
"after": { "brand": "Xiaomi", "category": "phone" }
✅ 替代
terms + size=10000的深度分页方案。
十、完整示例:电商数据分析
GET /sales/_search
{
"size": 0,
"query": {
"range": {
"created_at": {
"gte": "2024-01-01",
"lt": "2024-07-01"
}
}
},
"aggs": {
"monthly_sales": {
"date_histogram": {
"field": "created_at",
"calendar_interval": "month"
},
"aggs": {
"revenue": { "sum": { "field": "price" } },
"avg_order_value": { "avg": { "field": "price" } },
"top_brands": {
"terms": { "field": "brand", "size": 5 },
"aggs": {
"category_breakdown": {
"terms": { "field": "category" }
}
}
}
}
},
"overall_stats": {
"stats": { "field": "price" }
}
}
}
十一、总结:聚合类型速查表
| 聚合类型 | 用途 | 是否支持嵌套 |
|---|---|---|
terms | 按字段分组 | ✅ |
date_histogram | 时间序列分析 | ✅ |
range | 范围分组 | ✅ |
avg / sum | 数值统计 | ✅ |
cardinality | 去重计数 | ✅ |
percentiles | 分位数分析 | ✅ |
significant_terms | 异常项检测 | ✅ |
derivative | 变化量 | ✅ |
bucket_script | 自定义计算 | ✅ |
composite | 深度分页 | ✅ |
1107

被折叠的 条评论
为什么被折叠?



