如何用ElasticSearch DSL统计GT与MX共享的typeA嵌套条目数
需求:统计GT和MX客户共享的typeA条目数量
现有文档数据
以下是Elasticsearch中的文档(已修正JSON语法错误):
Document 1
{ "Id": 6000, "customerName": "GT", "pages": [ { "fieldType": "typeA", "fieldId": 1001 }, { "fieldType": "typeB", "fieldId": 1002 } ] }
Document 2
{ "Id": 6001, "customerName": "MX", "pages": [ { "fieldType": "typeA", "fieldId": 1001 } ] }
Document 3
{ "Id": 6002, "customerName": "MX", "pages": [ { "fieldType": "typeB", "fieldId": 1002 }, { "fieldType": "typeC", "fieldId": 1003 } ] }
Document 4
{ "Id": 6003, "customerName": "GT", "pages": [ { "fieldType": "typeA", "fieldId": 1005 }, { "fieldType": "typeC", "fieldId": 1003 } ] }
Document 5
{ "Id": 6004, "customerName": "MX", "pages": [ { "fieldType": "typeA", "fieldId": 1005 } ] }
需求说明
需要统计嵌套在pages字段中的typeA条目数量,但仅统计那些同时出现在customerName为GT和MX的文档中的条目——即找出两类客户文档共享的fieldId对应的typeA条目。示例中fieldId=1001和fieldId=1005符合条件,总计2个。
原尝试的DSL(无法满足需求)
以下查询仅能统计GT或MX的typeA条目,无法筛选出同时存在的共享条目:
{ "query": { "bool": { "must": [ { "bool": { "should": [ { "match": { "customerName": "CN" } }, { "match": { "customerName": "MX" } } ] }, { "nested": { "path": "pages", "query": { "term": { "fieldType": "typeA" } } } } } ] } } }
正确的DSL查询方案
要实现需求,需要通过嵌套聚合+桶筛选来找出同时被两类客户包含的typeA条目,具体DSL如下:
{ "size": 0, "query": { "bool": { "must": [ { "nested": { "path": "pages", "query": { "term": { "pages.fieldType": "typeA" } } } }, { "terms": { "customerName": ["GT", "MX"] } } ] } }, "aggs": { "nested_pages_context": { "nested": { "path": "pages" }, "aggs": { "filter_typeA_entries": { "filter": { "term": { "pages.fieldType": "typeA" } }, "aggs": { "group_by_fieldId": { "terms": { "field": "pages.fieldId" }, "aggs": { "count_distinct_customers": { "terms": { "field": "customerName" } }, "keep_only_shared_entries": { "bucket_selector": { "buckets_path": { "customerCount": "count_distinct_customers._bucket_count" }, "script": "params.customerCount == 2" } } } } } } } }, "total_shared_typeA_count": { "bucket_script": { "buckets_path": { "validBuckets": "nested_pages_context>filter_typeA_entries>group_by_fieldId._bucket_count" }, "script": "params.validBuckets" } } } }
关键逻辑说明
- 外层查询:先过滤出包含typeA嵌套条目,且客户为GT或MX的文档,缩小聚合范围。
- 嵌套聚合:进入
pages嵌套字段的上下文,确保聚合操作针对嵌套条目。 - 筛选typeA:仅保留
fieldType=typeA的嵌套条目。 - 按fieldId分组:将相同fieldId的条目归为一组。
- 客户去重计数:统计每个fieldId对应的不同客户数量。
- 桶筛选:只保留客户数量为2的分组(即同时被GT和MX包含的fieldId)。
- 最终统计:通过
bucket_script计算符合条件的分组数量,即为共享的typeA条目总数。
注意事项
- 确保
pages.fieldId字段为keyword类型(或使用其对应的keyword子字段,如pages.fieldId.keyword),否则分词会导致分组错误。 - 若使用Elasticsearch 7.x及以上版本,脚本默认使用Painless,无需额外配置。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

