Elasticsearch Query DSL 中 must / filter / should 详解(面试 & 实战必会)
这是 Java 高级工程师面试中 Elasticsearch 几乎必问的一题 。
很多人"会写 DSL",但说不清为什么这么写、性能差在哪、线上怎么选 。
这篇文档的目标:让你能写、能讲、能反问面试官。
1. must / filter / should 是什么?
它们都属于 bool query 的子句,用来组合多个条件。
json
{
"query": {
"bool": {
"must": [],
"filter": [],
"should": []
}
}
}
一句话先记住:
must = 必须匹配 + 参与打分
filter = 必须匹配 + 不打分(可缓存)
should = 可选匹配 + 影响打分
2. must:必须匹配,参与相关性打分
2.1 基本含义
- 条件 必须满足
- 参与
_score计算 - 常用于 全文检索
2.2 示例
json
{
"query": {
"bool": {
"must": [
{ "match": { "title": "elasticsearch" } }
]
}
}
}
2.3 适合放在 must 的查询
matchmatch_phrasemulti_match- 任何需要 相关性排序 的条件
2.4 面试加分点(为什么 must 慢)
- must 会参与 BM25 打分
- 每个文档都要算 score
- 在只做过滤时是纯浪费
👉 能不用 must 就别用 must
3. filter:必须匹配,但不参与打分(性能王者)
3.1 基本含义
- 条件 必须满足
- 不计算
_score - 结果可被缓存
3.2 示例
json
{
"query": {
"bool": {
"filter": [
{ "term": { "status": "ON" } },
{ "range": { "price": { "gte": 100, "lte": 500 } } }
]
}
}
}
3.3 适合放在 filter 的查询
term / termsrangeexistsids
3.4 filter 为什么快?
- 不算 score
- 可缓存(尤其是低基数条件)
- 多 shard 场景下优势明显
3.5 面试标准话术
精准条件、与相关性无关的,一律放 filter。
4. must vs filter 的真实对比(高频面试点)
| 对比项 | must | filter |
|---|---|---|
| 是否必须匹配 | ✅ | ✅ |
| 是否算 score | ✅ | ❌ |
| 是否可缓存 | ❌ | ✅ |
| 性能 | 较慢 | 很快 |
| 典型用途 | 全文检索 | 精准过滤 |
5. should:可选匹配,用来"加分"
5.1 基本含义
- 不是必须匹配
- 匹配到的文档 score 更高
- 常用于 相关性优化
5.2 示例
json
{
"query": {
"bool": {
"must": [
{ "match": { "title": "java" } }
],
"should": [
{ "match": { "tags": "elasticsearch" } },
{ "match": { "tags": "search" } }
]
}
}
}
👉 匹配 title=java 就能进结果
👉 同时匹配 tags 的会排得更靠前
5.3 minimum_should_match(面试常追问)
json
{
"bool": {
"should": [
{ "term": { "color": "red" } },
{ "term": { "size": "L" } },
{ "term": { "brand": "nike" } }
],
"minimum_should_match": 2
}
}
含义:
- 3 个 should 条件
- 至少满足 2 个
6. should 在不同场景下的"隐藏规则"(必会)
6.1 只有 should(没有 must / filter)
json
{
"bool": {
"should": [
{ "term": { "status": "ON" } },
{ "term": { "status": "OFF" } }
]
}
}
👉 至少匹配 1 个 should(默认)
6.2 有 must / filter + should
json
{
"bool": {
"must": [
{ "match": { "title": "java" } }
],
"should": [
{ "term": { "tags": "es" } }
]
}
}
👉 should 不再是必须条件
👉 只影响排序
7. 一个"标准工程级写法"(面试直接背)
json
{
"query": {
"bool": {
"must": [
{ "match": { "name": "iphone" } }
],
"filter": [
{ "term": { "status": "ON" } },
{ "range": { "price": { "gte": 1000 } } }
],
"should": [
{ "term": { "tags": "hot" } },
{ "term": { "tags": "new" } }
]
}
}
}
解释给面试官听:
- must:决定"搜什么"
- filter:决定"能不能进"
- should:决定"谁排前面"
8. Spring Boot 中的对应写法(加分)
java
BoolQueryBuilder bool = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("name", "iphone"))
.filter(QueryBuilders.termQuery("status", "ON"))
.filter(QueryBuilders.rangeQuery("price").gte(1000))
.should(QueryBuilders.termQuery("tags", "hot"))
.should(QueryBuilders.termQuery("tags", "new"));
9. 高频踩坑总结(面试官最爱)
- ❌ 全部条件都放 must(性能差)
- ❌ term 查询放 must(浪费 score)
- ❌ 以为 should 一定要匹配(不是)
- ❌ 忘了 minimum_should_match
10. 一句话总结(背这个就够)
must 决定"相关性",
filter 决定"对不对",
should 决定"谁更好"。
能 filter 就 filter,
少算 score,ES 才跑得快。