filter不计算相关性得分且可缓存,query强制评分不可缓存;filter限于bool.filter内仅支持无评分子句,query可自由嵌套;filter在低匹配率时性能更优,高匹配率时优势减弱;顶层filter能裁剪聚合数据源,post_filter则不能。

一、核心行为差异
当您构造一个Elasticsearch搜索请求时,系统会依据语句所处的上下文决定是否计算相关性得分。Filter仅执行二元判断——文档要么匹配,要么不匹配;Query则必须评估每个匹配文档与查询条件的契合程度,并输出_score值。这种根本性差异直接决定了二者在缓存机制、执行路径和适用场景上的分野。
1、Filter上下文中的查询子句完全跳过Lucene评分流程,不触发TF-IDF或字段长度归一化计算。
2、Query上下文强制激活BM25评分模型,对每个命中文档生成浮点型_score,用于后续排序。
3、Filter结果以位图(bitset)形式驻留内存,相同条件重复执行时直接复用该位图。
4、Query每次执行均需重新遍历倒排索引并重算得分,无法利用历史执行结果。
二、缓存机制实现方式
Elasticsearch对Filter自动启用查询缓存,但该缓存并非简单地保存JSON响应,而是持久化底层匹配文档的ID集合标识。系统通过稀疏性预判与LRU淘汰策略管理缓存生命周期,确保高频低基数过滤条件获得最大加速收益。
1、首次执行Filter时,ES扫描段(segment)内所有文档,生成长度等于该段文档总数的二进制数组。
2、数组中位置i为1表示段内第i个文档满足Filter条件,为0则表示不满足。
3、当同一Filter被多次调用且命中率稳定,该位图被提升至节点级查询缓存(query cache)中。
4、若某段发生refresh或merge操作,关联的Filter缓存条目将被自动标记为失效并清除。
三、DSL语法结构约束
Filter不能脱离布尔查询(bool query)独立存在,其语法位置被严格限定在bool.filter数组内;而Query可作为顶层query字段值,也可嵌套于bool.must、bool.should等任意子句中。这种结构差异反映了ES对二者语义边界的硬性划分。
1、合法Filter写法必须包裹在"query": {"bool": {"filter": [...]}}结构中。
2、Filter内部禁止使用match、multi_match、wildcard等全文检索类查询子句。
3、Filter允许使用的子句仅限term、terms、range、exists、bool(含filter子句)、geo_bounding_box等无评分能力类型。
4、Query可自由混合全文检索与结构化条件,例如在must中同时包含match和range子句。
四、性能表现触发条件
Filter的性能优势并非恒定存在,其实际执行效率高度依赖数据分布特征与查询模式。当过滤条件返回大量文档(稠密结果)时,位图操作开销可能反超Query的局部评分计算,此时性能拐点出现。
1、Filter在匹配文档占比低于总文档数10%时,通常比同等条件的Query3–8倍。
2、当Filter结果集超过段文档总数的60%,位图遍历成本上升,与Query性能差距缩小甚至逆转。
3、多Filter组合采用位图AND运算,比逐个Query嵌套执行的must逻辑节省至少两次倒排索引访问。
4、对keyword类型字段执行term Filter,速度可达text字段match Query的15倍以上。
五、聚合作用域影响机制
Filter置于顶层bool.filter中时,会先于聚合(aggs)执行,从而缩小整个聚合计算的数据范围;若误将相同条件置于query上下文中,则聚合将在全量命中文档上运行,导致资源浪费与结果偏差。
1、在aggs外部定义filter,聚合仅处理filter输出的子集文档,内存占用与耗时显著降低。
2、若将过滤逻辑写入aggs内的filter聚合(如filters agg),则属于桶内二次过滤,不改变主聚合数据源。
3、使用post_filter字段添加的Filter,虽能限制最终返回文档,但对aggs无任何裁剪作用,聚合仍基于原始query结果运行。
4、必须确保时间范围、状态码等高选择性条件置于顶层filter中,而非嵌套在query内。










