Elasticsearch中top_hits聚合后post_filter失效问题求助
解决Elasticsearch聚合后过滤最新状态不为Success的用户问题
问题原因
你当前使用的post_filter无法生效的核心原因是:post_filter仅作用于原始搜索结果文档,不会影响聚合桶的生成。聚合的执行顺序是在query之后、post_filter之前,所以即使你过滤了原始文档,聚合依然会保留所有userId的桶(比如u3的桶依然存在,因为他有符合query条件的原始文档),最终聚合结果还是会包含u3的最新Success记录。
另外你原post_filter里的"failure"是小写,而数据中状态是首字母大写的"Failure",这也会导致过滤无效,但这不是核心问题。
解决方案:使用bucket_selector聚合过滤聚合桶
要在服务端层面过滤掉最新状态为Success的用户,需要使用bucket_selector聚合,它可以在聚合桶生成后,根据桶内的结果过滤掉不符合条件的桶。
完整查询语句
{ "query": { "bool": { "filter": [ { "range": { "data.time": { "gte": "1719543600000", "lte": "1719584179015", "format": "epoch_millis" } } }, { "query_string": { "query": "data.type:\"user-stats\"" } } ] } }, "aggs": { "group_by_userId": { "terms": { "field": "data.userId.keyword" }, "aggs": { "users_last_status": { "top_hits": { "size": 1, "sort": [ { "data.time": { "order": "desc" } } ], "_source": ["data.userId", "data.status", "data.time"] } }, "exclude_success_users": { "bucket_selector": { "buckets_path": { "latestStatus": "users_last_status.hits.hits.0._source.data.status" }, "script": "params.latestStatus != 'Success'" } } } } }, "size": 0 }
关键说明
size: 0:不需要返回原始文档,仅获取聚合结果,减少数据传输量users_last_status:通过top_hits聚合获取每个用户最新的一条记录,并指定返回需要的字段(避免返回冗余数据)exclude_success_users:bucket_selector聚合通过脚本检查每个桶的最新状态是否为Success,如果是则排除该桶,最终仅保留最新状态不为Success的用户桶
聚合结果解析
执行上述查询后,聚合结果中的group_by_userId.buckets只会包含u1和u2的桶,每个桶的users_last_status.hits.hits里就是该用户的最新记录,与你的期望输出一致。
内容的提问来源于stack exchange,提问作者Techi
相关产品推荐
相关产品推荐

