一、基本概念对比
| 特性 | match 查询 | match_phrase 查询 |
|---|---|---|
| 查询类型 | 全文查询 | 短语查询 |
| 分词处理 | 会先分析查询字符串 | 会先分析查询字符串 |
| 匹配要求 | 包含任意分词即可 | 必须包含全部分词且顺序一致 |
| 近似匹配 | 支持 | 可通过 slop 参数支持 |
| 适用场景 | 宽松搜索 | 精确短语匹配 |
二、实际测试示例
1. 准备测试数据
PUT /car_index
{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "ik_max_word" // 使用中文分词器
}
}
}
}
PUT /car_index/_doc/1
{
"name": "宝马法拉利兰博基尼"
}
PUT /car_index/_doc/2
{
"name": "宝马兰博基尼布加迪威龙"
}
2. match 查询测试
查询请求:
GET /car_index/_search
{
"query": {
"match": {
"name": "宝马法拉利"
}
}
}
查询结果:
{
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"hits": [
{
"_id": "1",
"_score": 1.4384104,
"_source": {
"name": "宝马法拉利兰博基尼"
}
},
{
"_id": "2",
"_score": 0.5753642,
"_source": {
"name": "宝马兰博基尼布加迪威龙"
}
}
]
}
}
结果分析:
- 文档1:包含"宝马"和"法拉利",匹配度高,得分高
- 文档2:只包含"宝马",匹配度低,得分低
- 两文档都返回,因为match查询只需要匹配部分词项
3. match_phrase 查询测试
查询请求:
GET /car_index/_search
{
"query": {
"match_phrase": {
"name": "宝马法拉利"
}
}
}
查询结果:
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"hits": [
{
"_id": "1",
"_score": 1.4384104,
"_source": {
"name": "宝马法拉利兰博基尼"
}
}
]
}
}
结果分析:
- 只有文档1被返回,因为它完整包含"宝马法拉利"这个短语
- 文档2虽然包含"宝马"和"兰博基尼",但不包含连续的"宝马法拉利"短语
三、核心差异详解
1. 分词与匹配方式
match查询:
- 将"宝马法拉利"分词为["宝马", "法拉利"]
- 查找包含任意一个词的文档
- 匹配更多词的文档得分更高
match_phrase查询:
- 将"宝马法拉利"分词为["宝马", "法拉利"]
- 查找必须包含这两个词且顺序一致的文档
- 默认要求词项相邻(可通过slop调整)
2. 评分机制差异
match评分考虑因素:
- 词项频率(TF)
- 逆文档频率(IDF)
- 字段长度归一化
- 协调因子(匹配词项比例)
match_phrase额外考虑:
- 词项位置关系
- 词项间隔距离(当使用slop时)
四、高级用法
1. match_phrase 的 slop 参数
允许短语中的词项有一定间隔:
GET /car_index/_search
{
"query": {
"match_phrase": {
"name": {
"query": "宝马 兰博基尼",
"slop": 1 // 允许中间有1个词间隔
}
}
}
}
结果:会匹配到文档2,因为"宝马"和"兰博基尼"中间没有其他词
2. 多字段匹配
GET /car_index/_search
{
"query": {
"multi_match": {
"query": "宝马法拉利",
"type": "phrase", // 使用短语匹配
"fields": ["name", "description"]
}
}
}
五、使用场景建议
适合使用 match 的场景
- 用户搜索框的一般搜索
- 需要模糊匹配的内容检索
- 对匹配精确度要求不高的场景
适合使用 match_phrase 的场景
- 精确的产品名称搜索
- 名人姓名、专业术语搜索
- 需要保持词组完整性的搜索
- 法律、专利等需要精确匹配的文档检索
六、性能考虑
-
match查询:
- 性能通常更好
- 可以利用倒排索引的优势
- 结果集通常更大
-
match_phrase查询:
- 需要额外的位置信息计算
- 当使用大slop值时性能下降明显
- 结果集更精确但可能更小
七、最佳实践
-
对同一字段同时提供两种搜索方式:
GET /products/_search { "query": { "bool": { "should": [ { "match": { "name": "宝马法拉利" } }, { "match_phrase": { "name": "宝马法拉利" } } ] } } } -
对重要字段使用多字段映射:
PUT /products { "mappings": { "properties": { "name": { "type": "text", "fields": { "keyword": { "type": "keyword" }, "phrase": { "type": "text", "analyzer": "phrase_analyzer" } } } } } }
通过合理选择 match 和 match_phrase 查询,可以平衡搜索的精确度和召回率,为用户提供更符合预期的搜索结果。