如何在ElasticSearch中统计指定两类文档间共享的字段值数量?
ElasticSearch统计两类文档共享字段值的数量
要统计customerName取指定两个值(比如CN和MX)的文档中,同时出现的customerValue值的数量,本质是找出两类文档共享的customerValue并统计其去重后的个数,可以通过ElasticSearch的聚合功能实现,以下是具体的DSL查询方案:
直接统计共享值数量的DSL
{ "size": 0, "aggs": { "shared_customer_value_count": { "cardinality": { "field": "customerValue", "filter": { "bool": { "must": [ { "bool": { "should": [ { "term": { "customerName": "CN" } }, { "term": { "customerName": "MX" } } ], "minimum_should_match": 2 } } ] } } } } } }
方案说明
size: 0:仅返回聚合结果,不返回具体文档,提升查询效率shared_customer_value_count:用cardinality(基数统计)聚合直接计算符合条件的customerValue去重数量- 嵌套的
bool过滤器:要求customerName同时关联CN和MX的文档(minimum_should_match: 2表示两个条件都要满足),确保统计的是两类文档中都出现的customerValue
针对你给出的示例数据,该查询会返回shared_customer_value_count的值为1,因为customerValue=10同时出现在CN和MX的文档中。
带分组验证的DSL(适合查看具体共享值的场景)
如果需要同时查看具体哪些customerValue是共享的,可以使用嵌套聚合:
{ "size": 0, "aggs": { "group_by_customer_value": { "terms": { "field": "customerValue" }, "aggs": { "has_cn": { "filter": { "term": { "customerName": "CN" } } }, "has_mx": { "filter": { "term": { "customerName": "MX" } } }, "filter_shared_values": { "bucket_selector": { "buckets_path": { "cn_doc_count": "has_cn._count", "mx_doc_count": "has_mx._count" }, "script": "params.cn_doc_count > 0 && params.mx_doc_count > 0" } } } } } }
方案说明
group_by_customer_value:按customerValue分组,每个组下分别统计该值对应CN和MX的文档数filter_shared_values:用bucket_selector脚本筛选出同时存在CN和MX文档的分组(即两个分组的文档数都大于0)- 最终返回的
group_by_customer_value下的bucket,就是所有共享的customerValue,统计这些bucket的数量即可得到结果
注意事项
- 确保
customerValue和customerName字段支持聚合:如果字段是text类型,需要开启fielddata或者使用对应的keyword子字段(比如customerName.keyword) - 数据量较大时,优先使用第一种基数统计的方案,性能更优
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

