迁移统计应用至MySQL+ElasticSearch v6:嵌套文档聚合问询
解决ElasticSearch v6嵌套文档的聚合问题
首先得明确:ES的nested类型字段和MySQL里的关联子表逻辑完全不一样——嵌套字段里的每个对象都是独立存储的子文档,和根文档是分离的。所以直接对raw_results.result或raw_results.code做聚合是无效的,必须先通过nested聚合进入嵌套文档的上下文,才能在里面做子聚合。
基础嵌套聚合示例(统计raw_results.code的出现次数)
比如你想统计所有文档中,raw_results里各个code的出现频次,可以用这个查询:
{ "size": 0, // 不需要返回具体文档,只取聚合结果 "aggs": { "enter_nested_context": { "nested": { "path": "raw_results" // 指定嵌套字段的路径,必须和映射一致 }, "aggs": { "code_frequency": { "terms": { "field": "raw_results.code", "size": 10 // 返回前10个高频code,按需调整 } } } } } }
多层嵌套聚合(比如先按zone分组,再统计每组的code分布)
如果需要结合根文档的字段(比如zone)做分层聚合,只需把nested聚合放在外层聚合的子聚合中:
{ "size": 0, "aggs": { "group_by_zone": { "terms": { "field": "zone", "size": 10 }, "aggs": { "enter_nested_raw_results": { "nested": { "path": "raw_results" }, "aggs": { "code_counts_per_zone": { "terms": { "field": "raw_results.code", "size": 10 } } } } } } } }
带过滤的嵌套聚合(只统计特定result值的code)
如果需要先筛选raw_results.result为特定值的子文档,再做聚合,可以在nested聚合内部加filter子聚合:
{ "size": 0, "aggs": { "enter_nested_context": { "nested": { "path": "raw_results" }, "aggs": { "filter_positive_results": { "filter": { "term": { "raw_results.result": "positive" // 筛选result为positive的子文档 } }, "aggs": { "code_counts_filtered": { "terms": { "field": "raw_results.code", "size": 10 } } } } } } } }
关键注意事项
- 所有针对嵌套字段的聚合、过滤操作,必须放在
nested聚合的上下文内部 - 引用嵌套字段时,必须写完整路径(比如
raw_results.code,不能只写code) - ES6的
nested聚合不支持反向嵌套(回到根文档上下文),如果需要关联根文档字段,要确保聚合层级正确
内容的提问来源于stack exchange,提问作者jmleroux
相关产品推荐
相关产品推荐

