bigywater.tech
Elasticsearch · 82

filter 聚合与查询过滤

真实对比query层bool.filter收窄整个请求所有聚合范围的行为,与filter聚合作为独立bucket节点能在同一次请求里并存整体视图与筛选后视图的真实差异,揭示filter聚合在对照统计场景下的真实价值。

query层bool.filter
真实收窄整个请求,聚合只看得到过滤后的数据
filter聚合
真实能在同一请求里并存整体与筛选后两份视图
实际价值
真实省去了发两次独立请求做对照统计的开销

做的事:真实对比query里的bool.filter限定范围、和用filter聚合单独圈出一个子范围这两种写法

代码真实索引5篇文档: active 3篇(cat=a,a,b) / inactive 2篇(cat=a,b) query层filter限定: POST /fa_test/_search {"query":{"bool":{"filter":{"term":{"status":"active"}}}}, "aggs":{"by_cat":{"terms":{"field":"cat"}}}} filter聚合: POST /fa_test/_search {"query":{"match_all":{}},"aggs":{ "overall_by_cat":{"terms":{"field":"cat"}}, "active_only":{"filter":{"term":{"status":"active"}},"aggs":{"by_cat":{"terms":{"field":"cat"}}}} }}

验证:query层的filter真实把整个请求都收窄了,聚合桶只看得到active范围内的数据

实测 · 本机 Elasticsearch 8.15.0 执行输出
query里bool.filter限定status=active:
→ by_cat桶: a(2) b(1)   ← 真实只统计到了active范围内的3篇文档

这跟本系列第57篇验证过的query层filter行为真实完全一致:一旦在query里加了过滤条件,这个条件真实会作用到整个请求的每一个部分,聚合真实只能看到过滤之后剩下的那部分文档,没有办法在同一个请求里再拿到"过滤之前"的整体统计。

验证:filter聚合真实能在同一个请求里,同时给出"整体视图"和"筛选后视图"两份对照数据

实测 · 本机执行输出
query整体不过滤(match_all),用filter聚合单独圈出active范围:

overall_by_cat(真实全部5篇,两种状态都算在内):
→ a(3) b(2)

active_only.by_cat(真实只统计filter聚合圈出的active这3篇):
→ a(2) b(1)

active_only这个filter桶本身的doc_count: 3
这组真实对比揭示了filter聚合真正的存在价值:它真实是一种bucket聚合,把自己内部的filter条件当成划定一个子集合的边界,但真实不会影响同一个请求里其他兄弟聚合的统计范围——本次实测overall_by_cat真实统计的是全部5篇文档,active_only这个filter桶内部的by_cat真实只统计被圈进来的那3篇active文档,两者真实在同一次请求、同一份响应里并存,互不干扰。这正是query层filter天然做不到的事情:如果真实想要同时展示"全站总览"和"仅看已激活用户"这两份统计数据做对比(比如运营报表里常见的"总量 vs 活跃占比"),用query层filter只能真实发两次请求各自过滤一遍;用filter聚合则真实只需要一次请求,把需要对比的子范围统计都作为平级的聚合节点并排放在aggs里即可,底层也真实只需要对文档集合扫描一遍就能同时算出所有视图,比发两次独立查询更省资源。

分步演示:query层filter与filter聚合从收窄整个请求到同时呈现多视图的完整对比

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

query层filter收窄整个请求,filter聚合能在一次请求里并存整体与筛选后视图
这一步新验证的过滤方式

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 filter 聚合与query层 bool.filter
    京ICP备2026067502号-1京公网安备11010502063487号