如何过滤Elasticsearch聚合结果中双字段为null的Buckets
过滤Elasticsearch聚合中subject和login均为null的桶
问题场景
当前查询会返回包含subject和login字段均为null的聚合桶,需求是从聚合结果中排除这类桶。原查询及返回的聚合结果如下:
原查询语句
{ "bool": { "must": [ { "bool": { "should": [ { "terms": { "username.d": [ "abc.com" ], "boost": 1 } }, { "terms": { "authorization_service.d": [ "gmail.com" ], "boost": 1 } } ], "must_not": [ { "exists": { "field": "username.email" } }, { "exists": { "field": "username.login" } } ], "boost": 1 } }, { "exists": { "field": "password.hash", "boost": 1 } } ], "adjust_pure_negative": true, "boost": 1 } }
原聚合结果示例
"aggregations": { "subjects": { "after_key": { "subject": null, "login": null, "authorization_service": "abc.com" }, "buckets": [ { "key": { "subject": null, "login": null, "authorization_service": "abc.com" }, "doc_count": 10 } ] } }
解决思路
可以通过查询阶段过滤或聚合阶段过滤两种方式实现需求,以下是具体方案:
方案一:查询阶段过滤(推荐,更高效)
在原查询的must_not中添加条件,直接排除subject和login均为null的文档,从源头上避免生成这类聚合桶。
修改后的查询语句:
{ "bool": { "must": [ { "bool": { "should": [ { "terms": { "username.d": [ "abc.com" ], "boost": 1 } }, { "terms": { "authorization_service.d": [ "gmail.com" ], "boost": 1 } } ], "must_not": [ { "exists": { "field": "username.email" } }, { "exists": { "field": "username.login" } }, // 新增:排除subject和login均为null的文档 { "bool": { "must": [ {"match": {"subject": null}}, {"match": {"login": null}} ] } } ], "boost": 1 } }, { "exists": { "field": "password.hash", "boost": 1 } } ], "adjust_pure_negative": true, "boost": 1 } }
方案二:聚合阶段过滤(灵活,适合无法修改主查询的场景)
使用bucket_selector聚合,在聚合结果生成后过滤掉subject和login均为null的桶(要求Elasticsearch版本2.0及以上)。
示例聚合语句(需结合原查询使用):
{ "aggs": { "subjects": { "composite": { "sources": [ {"subject": {"terms": {"field": "subject"}}}, {"login": {"terms": {"field": "login"}}}, {"authorization_service": {"terms": {"field": "authorization_service.d"}}} ] }, "aggs": { "filter_invalid_buckets": { "bucket_selector": { "buckets_path": { "subjectKey": "_key.subject", "loginKey": "_key.login" }, "script": "params.subjectKey != null || params.loginKey != null" } } } } } }
该脚本会保留subject或login至少有一个不为null的桶,直接过滤掉两者均为null的桶。
内容的提问来源于stack exchange,提问作者NQScalar
相关产品推荐
相关产品推荐

