深入学习 ElasticSearch 的搜索(三):match_phrase 查询
深入学习 ElasticSearch 的搜索(三):match_phrase 查询
match_phrase 是 ElasticSearch 中常用的短语查询。
它和 match 很像,都会分析查询文本,但 match_phrase 更严格。
它不只是要求 term 命中,还要求这些 term 在字段中的顺序和位置关系符合短语要求。
简单说:
match 关注“有没有这些词”,match_phrase 关注“这些词是不是按顺序靠在一起”。
一、基本写法
查询正文中包含短语 倒排索引 的文章:
POST article_search/_search
{
"query": {
"match_phrase": {
"content": "倒排索引"
}
}
}
match_phrase 适合查:
- 固定短语
- 连续词组
- 标题中的完整表达
- 需要顺序关系的文本
二、match_phrase 的执行过程
假设查询:
ElasticSearch 搜索
执行过程大致是:
- 查询文本经过 analyzer
- 得到多个 term
- 去倒排索引中找包含这些 term 的文档
- 再检查这些 term 的 position
- position 符合短语关系才算命中
所以 match_phrase 依赖倒排索引中的 position 信息。
如果字段没有保存位置信息,就无法正常支持短语匹配。
三、和 match 的区别
假设文档内容是:
ElasticSearch 的倒排索引是搜索能力的基础
查询:
{
"match": {
"content": "倒排索引 搜索"
}
}
match 可能命中,因为文档中有:
- 倒排
- 索引
- 搜索
但如果使用:
{
"match_phrase": {
"content": "倒排索引 搜索"
}
}
就不一定命中,因为“倒排索引”和“搜索”之间隔了其他词。
这就是二者差异:
match:词命中即可,比较宽松match_phrase:词要按顺序,并且位置关系要符合要求
四、slop:允许词之间有距离
match_phrase 默认要求 term 的位置比较严格。
如果希望中间允许间隔,可以使用 slop。
POST article_search/_search
{
"query": {
"match_phrase": {
"content": {
"query": "倒排索引 搜索",
"slop": 3
}
}
}
}
slop 可以理解成短语匹配时允许的移动距离。
它适合这种场景:
- 用户输入的是一个大概短语
- 文档中这些词不是完全连续
- 但词之间距离很近,也应该算相关
不过 slop 不宜设置过大,否则 match_phrase 会逐渐失去短语查询的意义。
五、对象写法:slop、analyzer、boost
match_phrase 有两种常见写法。
简写:
POST article_search/_search
{
"query": {
"match_phrase": {
"content": "倒排索引"
}
}
}
完整对象写法:
POST article_search/_search
{
"query": {
"match_phrase": {
"content": {
"query": "倒排索引",
"slop": 1,
"boost": 2
}
}
}
}
当只传查询文本时,简写更清楚。
当需要配置 slop、analyzer、boost 等参数时,就必须使用对象写法。
六、match_phrase_prefix:短语前缀查询
match_phrase_prefix 可以理解成短语查询的前缀版本。
例如:
POST article_search/_search
{
"query": {
"match_phrase_prefix": {
"title": "ElasticSearch m"
}
}
}
它会把最后一个 term 当成前缀处理,适合简单的输入联想。
但如果要做正式的搜索建议,不应该只依赖它,还可以考虑:
search_as_you_typecompletion suggesteredge_ngram
七、中文场景要注意分词
中文里使用 match_phrase 时,分词结果尤其重要。
例如查询:
倒排索引
如果 analyzer 结果是:
倒排 / 索引
那么 match_phrase 会检查 倒排 和 索引 是否按顺序相邻。
如果 analyzer 结果是:
倒 / 排 / 索 / 引
那么短语匹配的粒度就变成单字级别,可能带来更多误匹配。
所以排查时先看:
POST article_search/_analyze
{
"field": "content",
"text": "倒排索引"
}
只有 analyzer 结果合理,match_phrase 才能合理。
八、中文人名不一定适合只靠 match_phrase
如果搜索的是中文人名,例如:
张三
match_phrase 的效果高度依赖分词器。
如果分词器把它识别成:
张三
那短语查询比较自然。
如果分词器把它拆成:
张 / 三
查询语义就会退化成相邻 token 匹配,误命中风险会上升。
如果“人名”本身是业务对象,更稳的做法是单独建一个实体字段:
{
"chunk_text": "饭后,张三看着李四,没有说话。",
"entity_names": ["张三", "李四"]
}
其中:
chunk_text用text做正文全文搜索entity_names用keyword数组做人名精确检索
查询人名时用:
POST article_search/_search
{
"query": {
"term": {
"entity_names": "张三"
}
}
}
这比只靠正文分词更稳定。
九、match_phrase 适合什么场景
适合:
- 搜完整标题
- 搜固定短语
- 搜日志中的连续片段
- 搜文章里的明确表达
- 提高搜索结果精确度
例如:
POST article_search/_search
{
"query": {
"match_phrase": {
"title": "ElasticSearch 入门教程"
}
}
}
这比普通 match 更强调标题中是否出现了这个连续表达。
十、不适合什么场景
不适合:
- 用户随便输入多个关键词
- 希望尽量多召回结果
- 字段分词质量不稳定
- 只想查分类、状态、ID
如果用户输入的是:
ElasticSearch 安装 查询 倒排索引
这更像关键词搜索,通常应该先用 match,再考虑通过 bool 或评分策略优化。
十一、常见误区
1. match_phrase 不是完全等于原文包含
match_phrase 仍然会先分析查询文本。
所以它匹配的是分析后的 term 位置关系,不是直接做原始字符串匹配。
2. 查不到不一定是文档没有
如果 match_phrase 查不到,可能原因包括:
- analyzer 分词结果不符合预期
- 查询词顺序和文档中顺序不同
- 两个词之间距离超过了默认要求
- 字段没有合适的 position 信息
3. slop 不是越大越好
slop 越大,匹配越宽松,但结果也可能越不精确。
短语查询的价值就在于位置约束。
如果 slop 设置得太大,可能不如直接使用 match。
十二、一句话总结
match_phrase 适合查询连续短语。
它和 match 的核心区别是:
match 主要看 term 是否命中,match_phrase 还要看 term 的顺序和位置。
如果要查“固定表达”“连续标题”“短语片段”,优先考虑 match_phrase。
参考链接
-
Match phrase query
https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-match-query-phrase -
index_options
https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/index-options -
Match phrase prefix query
https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-match-query-phrase-prefix

更多推荐




所有评论(0)