Elasticsearch聚合问题:如何排除travel数组中active=false的城市?
Elasticsearch嵌套数组聚合:仅统计active=true的城市
问题背景
现有文档数据结构如下:
[ { "name": "Scott", "origin": "London", "travel": [ { "active": false, "city": "Berlin", "visited": "2020-02-01" }, { "active": true, "city": "Prague", "visited": "2020-02-15" } ] }, { "name": "Lilly", "origin": "London", "travel": [ { "active": true, "city": "Scotland", "visited": "2020-02-01" } ] } ]
要完成的聚合需求:
- 先按顶层
origin字段分桶 - 统计每个城市的访问人数,只算
travel数组里active=true的条目
之前用普通filter聚合时,只要文档里有一个travel.active=true的元素,就会把整个文档的travel数组都纳入统计,导致结果里还包含了active=false的Berlin,不符合要求。
期望的聚合输出:
{ "aggregations": { "origin": { "buckets": [ { "key": "London", "buckets": [ { "key": "travel_nested", "doc_count": 2, "buckets": [ { "key": "active_travel_filter", "doc_count": 2, "buckets": [ { "key": "Scotland", "doc_count": 1 }, { "key": "Prague", "doc_count": 1 } ] } ] } ] } ] } } }
解决方法
普通filter聚合没法针对嵌套数组的单个元素做精准过滤,必须用嵌套聚合(nested aggregation),把数组里的每个对象当作独立单元处理。
正确的聚合配置代码:
{ "from": 0, "aggs": { "origin": { "terms": { "field": "origin" }, "aggs": { "travel_nested": { "nested": { "path": "travel" }, "aggs": { "active_travel_filter": { "filter": { "term": { "travel.active": true } }, "aggs": { "city": { "terms": { "field": "travel.city.keyword" } } } } } } } } } }
核心要点
- 用
nested聚合指定path: "travel",让Elasticsearch把数组中的每个对象独立看待,而不是把整个数组当成一个字段。 - 先进入嵌套上下文,再用filter筛选
active=true的元素,最后对符合条件的城市进行分桶统计。 - 如果
travel.city是文本类型,必须用travel.city.keyword进行分桶,否则会按分词后的词汇聚合,结果不符合预期。
内容的提问来源于stack exchange,提问作者MikeByte
相关产品推荐
相关产品推荐

