Elasticsearch合并查询:单次请求获取结果与聚合过滤选项
解决方案:用Global聚合合并单次请求
完全可以把这两次请求合并成一次!核心思路是利用Elasticsearch的Global聚合——它能让聚合逻辑忽略当前查询中的filter条件,只基于你原始的搜索查询(也就是should里的内容)来计算聚合结果,这样就能在一次请求里同时拿到:
- 经过
filter过滤后的结果列表 - 不受当前过滤器影响的聚合选项(和你第二次请求的结果一致)
合并后的完整查询语句
{ "query": { "bool": { "should": [ { "match_phrase": { "title": { "query": "cooking", "boost": 2, "slop": 10 } } }, { "match": { "title": { "query": "cooking", "boost": 1 } } } ], "minimum_should_match": 1, "filter": [ { "match": { "is_paid": false } } ] } }, "sort": [], "from": 0, "size": 15, "aggs": { "global_agg": { "global": {}, "aggs": { "courseCount": { "terms": { "field": "provider", "size": 100 } }, "paidCount": { "terms": { "field": "is_paid", "size": 3 } }, "subjectCount": { "terms": { "field": "subject", "size": 30 } }, "levelCount": { "terms": { "field": "level", "size": 4 } }, "pacingCount": { "terms": { "field": "pacing_type", "size": 4 } } } } } }
关键细节说明
- 结果部分:外层的
query.bool.filter依然生效,返回的hits是经过is_paid: false过滤后的内容,和你第一次请求的结果完全一致 - 聚合部分:通过
global聚合包裹所有子聚合,这会让这些聚合忽略外层的filter条件,只基于should中的搜索查询(匹配title含"cooking"的文档)来计算统计数据,和你第二次请求的聚合结果完全相同 - 性能优化:单次请求避免了两次网络往返,性能会比原来的两次请求好很多,同时逻辑也更清晰
内容的提问来源于stack exchange,提问作者Raj Kumar
相关产品推荐
相关产品推荐

