ES 1.x 及更早版本里,query 和 filter 是两套完全独立的 DSL 体系;ES 2.0 做了底层统一,所有子句变成同一种查询对象,不再区分 query 类型、filter 类型,只区分执行上下文(query 上下文 /filter 上下文),同时废弃 filtered 查询、独立 and/or/not 过滤器。很多老业务直接升级后,匹配结果看着差不多,但打分、缓存、性能悄悄变了,必须重新回归验证。
一、ES1.x 时代:两套独立体系
- Query(查询):判断文档匹配程度,计算 _score 相关性分,用于全文检索排序;term、range、bool 都有独立的 query 版本,不自动缓存。
- Filter(过滤器):只判断匹配与否(是 / 否),不打分;term、range、bool 同样有独立 filter 版本,常用过滤器默认支持缓存,速度更快。
- 组合方式:必须用 filtered 查询把「query 部分」和「filter 部分」包在一起;多条件组合要用专门的 and / or / not 过滤器,语法割裂。
| 项目 | ES1.x | ES2.0+ |
|---|---|---|
| 对象体系 | query、filter 是两套不同对象 | 同一套查询对象,由上下文决定行为 |
| 打分逻辑 | query 算分,filter 永远不算分 | must/should 走 query 上下文(参与打分);filter/must_not 走 filter 上下文(不打分) |
| 组合写法 | filtered + and/or/not 过滤器 | bool 的 must /filter/should /must_not |
| 缓存 | filter 默认缓存,query 不缓存 | filter 上下文自动缓存,query 上下文不缓存 |
二、ES2.0 的核心改动:用上下文区分行为
合并之后,没有单独的 “filter 查询” 了,同一个 term/range/bool 子句,放在 bool.must 里就是算分,放在 bool.filter 里就是纯过滤:
- query 上下文:must、should → 计算相关性分数,影响排序
- filter 上下文:filter、must_not → 只做匹配,不参与打分,适合状态、时间、分类筛选
- filtered 查询标记废弃,官方推荐直接改写为 bool 查询:原来的 query 放进 must,原来的 filter 放进 filter 数组
1.x 老 filtered 写法
{
"query": {
"filtered": {
"query": { "match": { "title": "java" } },
"filter": { "term": { "status": "online" } }
}
}
}
2.0 标准改写
{
"query": {
"bool": {
"must": [{"match": {"title": "java"}}],
"filter": [{"term": {"status": "online"}}]
}
}
}
三、容易踩坑的静默变化(升级必须核验)
- 打分逻辑漂移:老代码里本来是 filter 的条件,如果迁移时误写到 must,条件会参与算分,排序结果直接变。
- 缓存不再无条件生效:1.x 很多 filter 默认缓存;2.0 + 是 filter 上下文才会走缓存策略,不是所有条件自动缓存。
- and/or/not 过滤器被移除:不能继续用老过滤器组合,必须改用 bool 嵌套。
- constant_score 语义变化:老版本常用来包装 filter 实现 “固定分数”,合并后要结合上下文重新核对。
- 空查询、全匹配逻辑:1.x 很多 filter 写法升级后,score 默认值、返回文档顺序会有差异。
四、迁移校验清单
- 区分业务条件:哪些是全文检索、需要参与打分(must);哪些是过滤条件、不参与打分(filter)。
- 逐条对比:升级前后,同一批搜索词的返回文档顺序、_score、总命中数。
- 性能对比:高频筛选条件,确认进入 filter 上下文,验证缓存命中率。
- 去掉废弃语法:filtered、and/or/not 过滤器全部清理,不要留兼容写法。
- 复杂嵌套:多层 bool 嵌套时,注意每一层子句所处上下文,内层 filter 不会被外层 must 影响。
五、后续版本延续
这套 “上下文驱动” 的模型,从 ES2.0 一直延续到 7.x、8.x,是现在 DSL 的底层规则;很多新人只学新版,不知道早年 query、filter 是两套东西,读老脚本很容易混淆。
【相关 FAQ】
问题 1:ES2.0 把 query 和 filter 合成一套,到底是改了什么?
回答 1:底层不再区分 query 对象、filter 对象,所有查询子句是同一套;不再靠对象类型决定是否打分,而是看它放在 bool 的 must/should(query 上下文,算分)还是 filter/must_not(filter 上下文,不算分),同时废弃了 filtered 查询。
问题 2:ES1.x 的 filtered 查询,升级 ES2.0 标准改成什么?
回答 2:改成 bool 查询,原来 filtered 内部的 query 放到 bool.must,原来的 filter 条件放到 bool.filter 数组,是最标准对齐写法。
问题 3:升级 ES2.0 之后,为什么文档命中数没变,但排序结果乱了?
回答 3:大概率是原来的 filter 条件迁移时写到 must 里,条件被纳入相关性打分,_score 计算逻辑改变,导致排序漂移;这类问题属于静默变更,不会直接报错,必须回归对比。
问题 4:ES2.0 之后 filter 上下文还会自动缓存吗?
回答 4:filter 上下文会走缓存策略,但不再像 1.x 所有 filter 默认缓存;ES 会根据子句类型、使用频率自动判断,不能假设写在 filter 里就一定缓存。
【参考资料】
[2015-07-15](Elastic 官方博客:ES2.0 query/filter 合并)Elastic Blog
[2026-10-26](腾讯云开发者社区:ES 考古 query filter 两套体系合并)腾讯云开发者社区
[Elastic 2.0 迁移文档 query DSL 废弃 filtered、and/or/not 过滤器] Elastic archive
[Elastic 2.x bool 查询官方文档 must/filter 上下文说明] Elastic Docs
【免责声明】
本文基于 ES1.x → ES2.0 的历史变更;ES 5/7/8 在上下文规则上大体延续,但缓存、score 计算细节仍有微调;跨版本升级,除了语法改造,务必做对照回归,重点核对排序、打分、性能。
本文来自作者[暗域闸口]投稿,不代表乌兰科技网立场,如若转载,请注明出处:https://www.wlcbnews.com/rgzn/202611/79.html
评论列表(4条)
我是乌兰科技网的签约作者“暗域闸口”!
希望本篇文章《ES 2.0 query/filter 体系合并考古|上下文机制、filtered 废弃、老查询迁移、静默风险校验》能对你有所帮助!
本站[乌兰科技网]内容主要涵盖:互联网行业的追踪与探索
本文概览:ES 1.x 及更早版本里,query 和 filter 是两套完全独立的 DSL 体系;ES 2.0 做了底层统一,所有子句变成同一种查询对象,不再区分 query 类型、filter 类型,只区分执行上下文(query 上下文 filter 上下文),同时废弃 filtered 查询、独立 and or not 过滤器。很多老业务直接升级后,匹配结果看着差不多,但打分、缓存、性能悄悄变了,必须重新回归验证。