首页/数据/NoSQL 速查/子聚合与按指标排序
Elasticsearch89 条

子聚合与按指标排序

聚合可以嵌套:外层分桶、内层再做指标或分桶聚合,形成两层统计;用 order 按子聚合结果排序,可以回答按业务指标排前 N 的问题。

NoSQL 速查数据更新于 2026-10-13

子聚合是什么

聚合可以嵌套:外层聚合负责分桶,内层聚合针对每个桶再做指标计算或继续分桶,形成两层甚至多层统计。最常见的形式是 terms 分桶后按 avg、sum 之类指标排序,用来回答「按某个维度排前 N」的问题,比如按国家看平均客单价最高的前五名。

基本信息

结构aggs 里再写 aggs,子聚合只作用于当前桶内的文档
按子聚合排序order: { "子聚合名": "desc" },也可用 _count、_key
常见内层聚合avg、sum、max、min、percentiles、cardinality,或再嵌一层 terms
结果合并子聚合先在分片本地计算,再在协调节点合并
适用版本Elasticsearch 7.x / 8.x 语法一致

典型使用场景

  • 按维度取 Top N:按桶内指标而不是文档数决定桶序
  • 两层统计:先按国家分桶,再看每个国家的客单价水平
  • 多级下钻:品类到商品的两层桶统计
  • 桶内条件细分:内层用 filter 聚合只看某种状态的文档
  • 配合 size: 0 只要统计结果,不返回文档本身以省带宽

嵌套聚合写法

嵌套聚合写法
GET /orders/_search
{
  "size": 0,
  "aggs": {
    "by_country": {
      "terms": { "field": "country", "size": 5, "order": { "avg_price": "desc" } },
      "aggs": {
        "avg_price": { "avg": { "field": "price" } },
        "paid_only": { "filter": { "term": { "status": "paid" } },
                       "aggs": { "sum_qty": { "sum": { "field": "qty" } } } }
      }
    }
  }
}

# 桶内再分桶:品类 -> 商品,桶数量按乘积增长
GET /orders/_search
{ "size": 0, "aggs": { "cat": { "terms": { "field": "category", "size": 10 },
  "aggs": { "sku": { "terms": { "field": "sku", "size": 5 } } } } } }

桶序写法读法

排序写法含义注意
order: { "avg_price": "desc" }按桶内 avg_price 从大到小取桶子聚合名拼错会直接报错
order: { "_count": "desc" }按桶内文档数排序,即默认行为不写 order 时就是这个效果
order: { "_key": "asc" }按分桶键本身排序仅对可排序的键类型有效
order: { "paid_only>sum_qty": "desc" }按多层路径下的指标排序路径用 > 连接,层级深易出错
terms 聚合默认只返回文档数最多的前十个桶,并且多分片下按各分片局部 Top N 合并,桶序按子聚合指标排序时结果可能出现偏差;需要精确遍历应改用 composite 聚合分页拉取。
结果里的 doc_count_error_upper_bound 大于 0 说明桶内计数可能存在误差,sum_other_doc_count 大于 0 说明还有桶未被返回;看统计口径是否完整,先检查这两个字段而不是直接看桶值。

易错点

  • 深层嵌套让每个桶组合都算一遍,两层 terms 各取 100 就是一万个桶,组合维度多时先估算桶规模再上线
  • 按子聚合排序会放大 terms 的 shard_size,桶多、指标多时聚合耗时与内存占用明显上升
  • terms 在多分片下只做局部 Top N 合并,按指标排序的结果可能与全量精确统计不一致,对账类需求要用 composite 或提前收缩数据
  • 子聚合名与 order 中引用的名字不一致会直接报错,改动聚合命名时容易漏掉 order 这一处

数据来源与参考

  • Elasticsearch Guide: Aggregations (nested)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌