You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elasticsearch:能否先折叠再聚合嵌套字段的数据?

Elasticsearch按指定字段分组并聚合嵌套字段

需求说明

我在使用Elasticsearch时,需要实现两个核心需求:

  1. 按groupId字段对文档分组,每组返回指定数量(比如前2条)的文档;
  2. 对每个分组内所有文档的people嵌套字段进行聚合,生成包含该分组全部人员的groupPeople字段,不受返回文档数量的限制。

示例数据准备

创建索引映射

PUT test/_mapping
{
  "properties": {
      "groupId":{
        "type":"keyword"
      },
      "id":{
        "type":"keyword"
      },
      "name":{
        "type":"text"
      },
      "people":{
        "type":"nested",
        "properties":{
          "email":{
            "type":"keyword"
          }
        }
      }
    }
}

插入测试文档

PUT test/_doc/1
{
  "name": "docs1",
  "groupId": "1",
  "people":[{
    "email":"people1@test.com"
  }]
}

PUT test/_doc/2
{
  "name": "docs2",
  "groupId": "1",
  "people":[{
    "email":"people2.1@test.com"
  },
  {
    "email":"people2.2@test.com"
  }]
}

PUT test/_doc/3
{
  "name": "docs3",
  "groupId": "2",
  "people":[{
    "email":"people3.1@test.com"
  },
  {
    "email":"people2.2@test.com"
  }]
}

PUT test/_doc/4
{
  "name": "docs4",
  "groupId": "1",
  "people":[{
    "email":"people4.1@test.com"
  },
  {
    "email":"people4.2@test.com"
  }]
}

PUT test/_doc/5
{
  "name": "docs5",
  "groupId": "3",
  "people":[{
    "email":"people5.1@test.com"
  },
  {
    "email":"people5.2@test.com"
  }]
}

原查询的局限性

之前使用collapse的方式只能获取每组内指定数量文档的people数据,无法聚合整个分组的所有人员(比如groupId=1分组有3条文档,共5个人员,但原查询只能拿到前2条文档的3个人员)。

解决方案:使用聚合组合实现

通过terms聚合按groupId分组,同时嵌套两个子聚合:

  • top_docs:用top_hits返回每组前2条文档;
  • group_people:用nested聚合+terms聚合统计分组内所有人员的email,再用top_hits或terms返回全部人员。

最终查询语句

GET test/_search
{
  "size": 0, // 不返回顶层hits,只看聚合结果
  "aggs": {
    "group_by_groupId": {
      "terms": {
        "field": "groupId",
        "size": 10 // 控制返回的分组数量
      },
      "aggs": {
        "top_docs": {
          "top_hits": {
            "size": 2 // 每组返回前2条文档
          }
        },
        "group_people": {
          "nested": {
            "path": "people"
          },
          "aggs": {
            "all_people": {
              "terms": {
                "field": "people.email",
                "size": 100 // 控制返回的人员数量,确保覆盖所有人员
              }
            }
          }
        }
      }
    }
  }
}

查询结果说明

返回的聚合结果中,每个groupId分组会包含:

  1. top_docs:该分组的前2条完整文档;
  2. group_people.all_people:该分组内所有人员的email统计(自动去重),比如groupId=1会包含people1@test.com、people2.1@test.com、people2.2@test.com、people4.1@test.com、people4.2@test.com这5个人员。

如果需要保留重复的人员(比如同一email出现多次也保留),可以将terms聚合替换为top_hits聚合:

"group_people": {
  "nested": {
    "path": "people"
  },
  "aggs": {
    "all_people": {
      "top_hits": {
        "size": 100,
        "_source": ["people.email"]
      }
    }
  }
}

内容的提问来源于stack exchange,提问作者feng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:25:22