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。


相关推荐
Dxy123931021614 小时前
Elasticsearch 索引与映射:为你的数据打造一个“智能仓库”
大数据·elasticsearch·搜索引擎
倒流时光三十年19 小时前
SpringBoot 数据库同步 Elasticsearch 性能优化
数据库·spring boot·elasticsearch
星辰_mya21 小时前
Elasticsearch更新了分词器之后
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客21 小时前
Elasticsearch:Workflows 介绍 - 9.3
大数据·数据库·人工智能·elasticsearch·ai·全文检索
星辰_mya1 天前
Elasticsearch主分片数写入后不能改
大数据·elasticsearch·搜索引擎
春日见1 天前
vscode代码无法跳转
大数据·人工智能·深度学习·elasticsearch·搜索引擎
那起舞的日子2 天前
ElasticSearch系列-3-java端整合CURD
elasticsearch
历程里程碑2 天前
普通数组----最大子数组和
大数据·算法·elasticsearch·搜索引擎·排序算法·哈希算法·散列表
星辰_mya2 天前
Elasticsearch之下
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客2 天前
跳过 MLOps:通过 Cloud Connect 使用 EIS 为自管理 Elasticsearch 提供托管云推理
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索