ElasticSearch:match和match_phrase区别

224 阅读3分钟

一、基本概念对比

特性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 的场景

  1. 用户搜索框的一般搜索
  2. 需要模糊匹配的内容检索
  3. 对匹配精确度要求不高的场景

适合使用 match_phrase 的场景

  1. 精确的产品名称搜索
  2. 名人姓名、专业术语搜索
  3. 需要保持词组完整性的搜索
  4. 法律、专利等需要精确匹配的文档检索

六、性能考虑

  1. match查询

    • 性能通常更好
    • 可以利用倒排索引的优势
    • 结果集通常更大
  2. match_phrase查询

    • 需要额外的位置信息计算
    • 当使用大slop值时性能下降明显
    • 结果集更精确但可能更小

七、最佳实践

  1. 对同一字段同时提供两种搜索方式:

    GET /products/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "match": {
                "name": "宝马法拉利"
              }
            },
            {
              "match_phrase": {
                "name": "宝马法拉利"
              }
            }
          ]
        }
      }
    }
    
  2. 对重要字段使用多字段映射:

    PUT /products
    {
      "mappings": {
        "properties": {
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword"
              },
              "phrase": {
                "type": "text",
                "analyzer": "phrase_analyzer"
              }
            }
          }
        }
      }
    }
    

通过合理选择 match 和 match_phrase 查询,可以平衡搜索的精确度和召回率,为用户提供更符合预期的搜索结果。