Elasticsearch 聚合(Aggregations)详解

Elasticsearch 聚合(Aggregations)详解

目标很明确:
不是教你 API,而是教你在面试中把"聚合"讲清楚、讲专业、讲有取舍。

面试官一听就知道:你不是背 DSL 的,是线上真用过的。


1. 一句话先把聚合讲明白(开场必杀)

Elasticsearch 的聚合本质是:在倒排索引之上做分桶(bucket)+ 指标计算(metric),
先按条件筛选文档,再在内存中做统计分析。

如果你再补一句:

它不是 SQL 的 group by,而是分布式、多 shard 并行的统计框架。

------ 面试官基本会点头。


2. 聚合整体执行流程(为什么它"贵")

你要能讲这个流程,而不是只会写 DSL。

  1. Query 阶段:
    • bool / filter / must 先筛选命中文档
  2. 每个 shard 本地执行聚合:
    • 分桶(terms / range / date_histogram)
    • 计算指标(count / avg / sum)
  3. 协调节点 merge:
    • 合并各 shard 的 bucket
    • 再算 pipeline 聚合(如果有)

👉 结论:

  • 聚合 = CPU + 内存密集
  • shard 越多、bucket 越多,代价越高

3. 聚合的三大类(必须分类讲)

3.1 Bucket Aggregation(分桶)

回答关键词:"分组"

常见:

  • terms(最常用)
  • range
  • date_histogram
  • composite(高级)

例子:

json 复制代码
"aggs": {
  "brandAgg": {
    "terms": {
      "field": "brand",
      "size": 10
    }
  }
}

3.2 Metric Aggregation(指标)

回答关键词:"数值计算"

常见:

  • count
  • avg
  • sum
  • min / max
  • cardinality(去重数)
json 复制代码
"aggs": {
  "avgPrice": {
    "avg": { "field": "price" }
  }
}

3.3 Pipeline Aggregation(对聚合结果再算)

这是高级工程师加分点

常见:

  • bucket_sort
  • derivative
  • moving_avg
  • bucket_script
json 复制代码
"aggs": {
  "brandAgg": {
    "terms": { "field": "brand" },
    "aggs": {
      "avgPrice": { "avg": { "field": "price" } },
      "sortBucket": {
        "bucket_sort": {
          "sort": [{ "avgPrice": { "order": "desc" } }]
        }
      }
    }
  }
}

👉 你可以说:
"pipeline 是在协调节点对 bucket 再做一次计算。"


4. terms 聚合:为什么它最容易出事(必问)

4.1 terms 的真实行为

  • 每个 shard 先取 top N
  • 协调节点再合并
  • 不是全局精确 top N

相关参数:

  • size
  • shard_size
json 复制代码
"terms": {
  "field": "brand",
  "size": 10,
  "shard_size": 100
}

👉 面试官想听你说这句:

terms 默认是近似结果,不是绝对精确。


4.2 高基数字段的坑

  • userId、orderId 这类字段
  • terms 聚合会:
    • 内存暴涨
    • GC 压力大
    • 甚至 OOM

工程经验回答:

  • 控制 size
  • 用 composite
  • 或离线算(ES 不适合)

5. composite aggregation(真正"像懂的人")

5.1 composite 是干嘛的?

对 bucket 本身做分页

适合场景:

  • 品牌很多
  • 类目很多
  • 需要"翻页展示聚合结果"

5.2 DSL 示例

json 复制代码
"aggs": {
  "brandAgg": {
    "composite": {
      "size": 100,
      "sources": [
        { "brand": { "terms": { "field": "brand" } } }
      ],
      "after": { "brand": "nike" }
    }
  }
}

👉 类比 search_after,但这是 bucket 的 search_after


6. 聚合 + filter:性能意识的分水岭

❌ 错误写法:

json 复制代码
"must": [
  { "term": { "status": "ON" } }
]

✅ 正确写法:

json 复制代码
"filter": [
  { "term": { "status": "ON" } }
]

你要说得出口:

聚合之前的条件,一定尽量放 filter,
不算 score、还能缓存,聚合才跑得动。


7. 聚合 + 分页:面试官常挖的坑

7.1 hits 分页 ≠ 聚合分页

  • search_after 只影响 hits
  • 聚合 始终基于 query 的全集

👉 这句话说出来就很专业。

7.2 正确工程设计

  • 聚合条件不变 → 聚合单独算 / 缓存
  • 翻页只翻 hits,不重复算 aggs

8. Spring Boot 解析聚合(你要会)

java 复制代码
SearchHits<ProductDoc> hits =
    elasticsearchOperations.search(query, ProductDoc.class);

ParsedStringTerms terms = hits.getAggregations().get("brandAgg");

for (Terms.Bucket b : terms.getBuckets()) {
    String key = b.getKeyAsString();
    long count = b.getDocCount();
}

9. 面试官最爱追问的 5 个问题(附回答思路)

Q1:terms 聚合准吗?

不完全准,多 shard 场景是近似,需要调 shard_size 或换 composite。

Q2:为什么不能对 text 聚合?

text 会分词,且不开启 doc_values;应该用 keyword。

Q3:聚合慢怎么优化?

filter 前置、减少 bucket 数、避免高基数字段、必要时离线算。

Q4:聚合能分页吗?

hits 能分页,bucket 用 composite。

Q5:ES 适合做报表吗?

小规模可以,复杂 BI 更适合 ClickHouse / OLAP。


10. 一句话总结(背这个)

聚合不是 group by,
是分布式分桶统计。
bucket 要少,filter 要前,
高基数别硬刚,
真报表别指望 ES。


相关推荐
ProgrammingWay3 小时前
ES常用API总结
elasticsearch·全文检索
Dxy12393102165 小时前
Elasticsearch 8.13.4 关键词如何高亮显示
大数据·elasticsearch
李迟5 小时前
2025年12月个人工作生活总结
大数据·elasticsearch·生活
ELI_He9996 小时前
SeaTunnel 编译
大数据·mysql·elasticsearch·database·flume
yumgpkpm6 小时前
银行的数据智能平台和Cloudera CDP 7.3(CMP 7.3)的技术对接
数据库·人工智能·hive·hadoop·elasticsearch·数据挖掘·kafka
G皮T7 小时前
【Elasticsearch】查询性能调优(七):为什么计数对性能影响如此之大?
大数据·elasticsearch·搜索引擎·全文检索·索引·查询·opensearch
Albert.H.Holmes8 小时前
Elasticsearch学习
大数据·学习·elasticsearch
Biehmltym1 天前
【AI】09AI Agent LLM → Streaming → Session 记录 的完整链路
大数据·人工智能·elasticsearch
小湘西1 天前
Elasticsearch 的一些默认配置上下限
java·大数据·elasticsearch