如何基于子桶聚合文档数过滤桶聚合结果?排除含指定标签用户
Elasticsearch查询:排除含指定标签的用户ID
需求
编写Elasticsearch查询,排除所有存在至少一篇文档的tag字段值为TAG A或TAG B的userId。
索引数据示例
[ { "_index": "tags-3", "_type": "_doc", "_id": "YYYYYYY", "_score": 10.272416, "_source": { "id": "YYYYYYY", "userId": "User1", "tag": "TAG A" } }, { "_index": "tags-3", "_type": "_doc", "_id": "ZZZZZZ", "_score": 10.272416, "_source": { "id": "ZZZZZZ", "userId": "User1", "tag": "TAG B" } }, { "_index": "tags-3", "_type": "_doc", "_id": "ZZZZZZ", "_score": 10.272416, "_source": { "id": "ZZZZZZ", "userId": "User2", "tag": "TAG A" } }, { "_index": "tags-3", "_type": "_doc", "_id": "ZZZZZZ", "_score": 10.272416, "_source": { "id": "ZZZZZZ", "userId": "User2", "tag": "TAG D" } }, { "_index": "tags-3", "_type": "_doc", "_id": "ZZZZZZ", "_score": 10.272416, "_source": { "id": "ZZZZZZ", "userId": "User4", "tag": "TAG D" } } ]
期望输出
{ "_index": "tags-3", "_type": "_doc", "_id": "ZZZZZZ", "_source": { "userId": "User4" } }
逻辑说明
User4的所有文档中tag字段从未出现TAG A或TAG B,因此保留User1、User2分别存在含TAG A/TAG B的文档,因此被排除
实现方案
步骤1:获取需排除的用户列表
先通过聚合查询,找出所有存在TAG A或TAG B标签的userId:
{ "size": 0, "query": { "terms": { "tag": ["TAG A", "TAG B"] } }, "aggs": { "excluded_users": { "terms": { "field": "userId", "size": 10000 } } } }
该查询会返回所有需要排除的userId集合(示例中为User1、User2)。
步骤2:查询符合条件的用户文档
用步骤1得到的排除列表,编写查询获取剩余用户的文档:
{ "query": { "bool": { "must_not": [ { "terms": { "userId": ["User1", "User2"] } } ] } }, "_source": ["userId"] }
此查询会返回所有未被排除的用户文档(示例中仅User4的文档)。
一步到位的聚合筛选(仅获取用户ID)
如果只需要得到符合条件的userId,可以直接用聚合筛选:
{ "size": 0, "aggs": { "all_users": { "terms": { "field": "userId" }, "aggs": { "has_excluded_tag": { "filter": { "terms": { "tag": ["TAG A", "TAG B"] } } }, "valid_users": { "bucket_selector": { "buckets_path": { "tag_count": "has_excluded_tag._count" }, "script": "params.tag_count == 0" } } } } } }
该聚合会直接返回所有无违规标签的userId,无需分两步操作。
内容的提问来源于stack exchange,提问作者xplat
相关产品推荐
相关产品推荐

