全文搜索
全文搜索:match、match_phrase、query_string 什么时候用哪个
用户在搜索框输入 "iPhone 15 Pro Max",你的 ES 应该怎么查?
你会想:不就是个 match 吗。但如果用户输的是 "iPhone 15 -mini"(排除 mini)、"title:iPhone AND price:[5000 TO 10000]"(高级语法)、或者 "iphne 15"(拼写错误)呢?
ES 提供了多种全文搜索方式,每一种都有自己最适合的场景。选错了,用户搜不到想要的东西;选得太重,集群压力上来。本篇逐一拆解。
Match:最通用的全文搜索
match 是 90% 场景下你该用的查询。它把搜索词用分词器拆开,然后去倒排索引里匹配。
GET /products/_search
{
"query": {
"match": {
"title": "iPhone 15 Pro Max"
}
}
}
输入 "iPhone 15 Pro Max" 经标准分词器处理后变成 ["iphone", "15", "pro", "max"],然后 ES 去搜包含这些 term 的文档。默认是 OR 逻辑——文档包含任意一个 term 就算命中。
改为 AND 逻辑
{
"match": {
"title": {
"query": "iPhone 15 Pro Max",
"operator": "and"
}
}
}
现在文档必须包含全部四个 term。结果更精准但更少。
更灵活:minimum_should_match
{
"match": {
"title": {
"query": "iPhone 15 Pro Max",
"minimum_should_match": "75%"
}
}
}
4 个 term 中至少匹配 3 个(75%)。比 AND 宽松,比 OR 精准。
Match Phrase:短语精确匹配
用户搜 "iPhone 15",你不想返回"iPhone 壳适用于 15 寸笔记本"——term 顺序和位置必须一致。
GET /products/_search
{
"query": {
"match_phrase": {
"title": "iPhone 15"
}
}
}
match_phrase 要求所有 term 按原顺序出现,且位置连续(slop 默认为 0)。
Slop:允许间隔
{
"match_phrase": {
"title": {
"query": "iPhone 15",
"slop": 2
}
}
}
slop: 2 允许 term 之间最多间隔 2 个位置。"iPhone 白色 15" 可以命中,"iPhone 全面屏 旗舰 15" 不行(间隔了 3 个)。
适用场景:搜标题、搜公司名、搜专有名词。
Multi Match:一次搜多个字段
用户输入一个关键词,你希望同时搜标题、描述、品牌:
GET /products/_search
{
"query": {
"multi_match": {
"query": "iPhone 15",
"fields": ["title^3", "brand^2", "description"]
}
}
}
title^3:标题匹配权重 3 倍——商品标题里包含关键字的排前面brand^2:品牌匹配权重 2 倍description:描述匹配权重 1 倍(默认)
Multi Match 的六种匹配模式
{
"multi_match": {
"query": "iPhone 15",
"fields": ["title^3", "description"],
"type": "best_fields" // 默认:以最高分的字段为准
}
}
| type | 行为 | 适用 |
|---|---|---|
best_fields |
取匹配分最高的单个字段的分数 | 关键词搜索,最常用 |
most_fields |
所有匹配字段的分数加起来 | 同义词/不同分词覆盖 |
cross_fields |
把多个字段当作一个大字段处理 | 姓名搜索、地址搜索 |
phrase |
在每个字段上跑 match_phrase | 精确短语搜索 |
phrase_prefix |
phrase + 最后一个 term 做前缀匹配 | 搜索提示 |
bool_prefix |
最后一个 term 做前缀,其余做 bool | 即搜即现 |
最常用的三个:best_fields(默认)、cross_fields(多字段融合)、phrase_prefix(自动补全)。
Query String:给高级用户的搜索引擎语法
GET /products/_search
{
"query": {
"query_string": {
"query": "title:iPhone AND price:[5000 TO 10000] -status:deleted",
"default_field": "title"
}
}
}
Query String 支持完整的 Lucene 查询语法:
iPhone AND 15 → 必须包含两个词
iPhone OR Samsung → 包含任意一个
title:"iPhone 15" → title 字段短语匹配
price:[5000 TO 10000] → 价格范围
-status:deleted → 排除
iPhone~ → 模糊匹配("iphne" 也能命中)
iPhone* → 通配符
适用场景:后台管理的高级搜索、内部工具。绝对不要让普通用户在搜索框里直接用 query_string——他们会输入 *:* 拉全量数据。
Match 全家桶对比
| 查询 | 分词 | 顺序敏感 | 得分计算 | 典型场景 |
|---|---|---|---|---|
match |
✅ | ❌ | 每个 term 独立算分再汇总 | 通用搜索 |
match_phrase |
✅ | ✅ | 顺序和位置一致性加分 | 标题搜索、专有名词 |
match_phrase_prefix |
✅ | ✅(最后一个 term 前缀) | 同上 | 搜索框自动补全 |
match_bool_prefix |
✅ | ✅(最后一个 term 前缀) | 高效前缀匹配 | 高性能自动补全 |
multi_match |
✅ | ❌(默认) | 多字段综合评分 | 搜多个字段 |
query_string |
✅ | 支持 | 完整 Lucene 语法 | 后台高级搜索 |
simple_query_string |
✅ | 有限 | 简化语法,容错好 | 用户直接输入复杂搜索 |
Simple Query String:折中方案
比 match 强大,比 query_string 安全:
{
"simple_query_string": {
"query": "iPhone +Pro -mini | Samsung",
"fields": ["title", "description"]
}
}
语法:
+必须包含-排除|或"iPhone 15"短语*通配符
适合:一个搜索框同时支持简单关键词和高级语法的场景。 比 query_string 更安全——不会因为用户输入非法语法而直接报错。
真实选型指南
用户的输入是关键词 → match / multi_match
用户的输入是完整短语 → match_phrase (slop=0~3)
用户的输入需要容错 → match + minimum_should_match="75%"
用户边输入边搜 → match_phrase_prefix / match_bool_prefix
用户需要高级搜索(后台) → query_string
用户需要高级搜索(前台) → simple_query_string
总结
大部分生产搜索只需要三招:
multi_match+best_fields做关键词搜索match_phrase+slop做精确短语匹配simple_query_string给高端用户一个灵活但安全的搜索口
query_string 留给后台管理员用——它功能最强但也最危险。