深入学习 ElasticSearch 的搜索(二):match 查询

match 是 ElasticSearch 全文检索中最常用的查询。

如果搜索对象是文章标题、正文、简介、评论这类自然语言文本,通常优先考虑 match

它的核心特点是:

查询文本会先经过 analyzer 分析,再用分析后的 term 去倒排索引中检索。

所以 match 不是简单的字符串包含,也不是直接拿原始查询内容去字段里扫描。


一、match 查询的基本写法

最简单的写法如下:

POST article_search/_search
{
  "query": {
    "match": {
      "content": "倒排索引"
    }
  }
}

含义是:

  • 查询 article_search 索引
  • content 字段中做全文检索
  • 查询内容是 倒排索引

如果 contenttext 字段,ElasticSearch 会使用字段对应的 analyzer 分析查询文本。


二、match 查询的执行过程

假设字段内容是:

倒排索引把文档到词的关系反过来

查询:

倒排索引

大致流程是:

  1. 查询文本进入 analyzer
  2. analyzer 生成一个或多个 term
  3. ElasticSearch 根据这些 term 查倒排索引
  4. 合并命中文档
  5. 计算 _score
  6. 返回结果

这也是为什么 analyzer 对搜索效果影响很大。

中文场景中,如果“倒排索引”被拆成了:

倒排 / 索引

和被拆成:

倒 / 排 / 索 / 引

搜索效果会完全不一样。


三、match 和 analyzer 的关系

可以用 _analyze 先看查询文本会被拆成什么。

POST article_search/_analyze
{
  "field": "content",
  "text": "倒排索引"
}

这个请求会使用 content 字段实际绑定的 analyzer。

排查搜索问题时,这一步很重要。

如果 _analyze 的结果和你预期不一致,后面的 match 查询也很难符合预期。


四、operator:控制多个 term 的关系

match 查询中,如果查询文本被分析成多个 term,默认通常是 OR 关系。

例如查询:

ElasticSearch 倒排索引

可能被分析成:

elasticsearch
倒排
索引

默认情况下,只要命中其中一部分 term,就可能出现在结果中。

如果希望所有 term 都必须命中,可以使用 operator

POST article_search/_search
{
  "query": {
    "match": {
      "content": {
        "query": "ElasticSearch 倒排索引",
        "operator": "and"
      }
    }
  }
}

常见取值:

  • or:默认,命中任意 term 即可
  • and:所有 term 都要命中

and 更严格,召回更少;or 更宽松,召回更多。


五、minimum_should_match:控制最低命中数量

如果不想像 and 那么严格,也不想像默认 or 那么宽松,可以使用 minimum_should_match

POST article_search/_search
{
  "query": {
    "match": {
      "content": {
        "query": "ElasticSearch 倒排索引 查询",
        "minimum_should_match": 2
      }
    }
  }
}

含义是:

查询分析出来的 term 中,至少要命中 2 个。

也可以使用百分比:

POST article_search/_search
{
  "query": {
    "match": {
      "content": {
        "query": "ElasticSearch 倒排索引 查询",
        "minimum_should_match": "70%"
      }
    }
  }
}

它适合处理用户输入较长的关键词,避免只命中一个很弱的词就返回太多无关结果。


六、match 查询会计算评分

match 属于 query context,会参与相关性评分。

例如:

POST article_search/_search
{
  "query": {
    "match": {
      "content": "ElasticSearch 搜索"
    }
  }
}

结果中的 _score 会受到多种因素影响:

  • 查询 term 是否命中
  • 命中了多少 term
  • term 在字段中出现的频率
  • term 在整个索引中是否稀有
  • 字段长度

所以 match 的结果通常是按相关性排序,而不是简单按文档 ID 或时间排序。


七、boost:给这条查询加权

match 支持 boost

它不是给字段永久加权,也不是给某条文档预先加权,而是:

让当前这条 query 子句在最终 _score 里更重要或更不重要。

例如:

POST article_search/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": {
              "query": "ElasticSearch",
              "boost": 3
            }
          }
        },
        {
          "match": {
            "content": {
              "query": "ElasticSearch",
              "boost": 1
            }
          }
        }
      ]
    }
  }
}

含义是:

  • 标题命中更重要
  • 正文命中也有价值,但权重低一些

这类写法在搜索排序里很常见。


八、analyzer:临时指定查询分析器

match 默认使用字段的 search_analyzer,如果没有配置 search_analyzer,通常使用字段的 analyzer

也可以在查询时临时指定 analyzer:

POST article_search/_search
{
  "query": {
    "match": {
      "content": {
        "query": "ElasticSearch 搜索",
        "analyzer": "standard"
      }
    }
  }
}

这适合做调试或少量特殊查询。

但业务上不建议到处临时指定 analyzer,否则索引时和搜索时的分析逻辑会变得很难维护。


九、fuzziness:容忍拼写错误

match 支持 fuzziness,用于处理拼写错误或字符误输入。

例如用户把 elasticsearch 输入成了 elasticsearh

POST article_search/_search
{
  "query": {
    "match": {
      "content": {
        "query": "elasticsearh",
        "fuzziness": "AUTO"
      }
    }
  }
}

fuzziness 本质上是编辑距离式的近似匹配。

它适合英文拼写容错、低频兜底召回,但不要把它当成“智能搜索”。尤其中文场景里,分词结果会强烈影响模糊匹配的效果,乱开可能导致召回过多、排序变差。


十、zero_terms_query:分析后没有 term 怎么办

如果查询文本经过 analyzer 后没有留下任何 term,可以用 zero_terms_query 控制行为。

POST article_search/_search
{
  "query": {
    "match": {
      "content": {
        "query": "the",
        "zero_terms_query": "none"
      }
    }
  }
}

常见取值:

  • none:默认,不匹配任何文档
  • all:匹配全部文档

实际业务中通常保持默认更安全,避免用户输入无效关键词时返回全部数据。


十一、operator=and 不等于 match_phrase

这一点很容易混淆。

POST article_search/_search
{
  "query": {
    "match": {
      "content": {
        "query": "ElasticSearch 倒排索引",
        "operator": "and"
      }
    }
  }
}

operator: "and" 的意思是:

查询文本分析出的多个 term 都必须命中。

但它不要求这些 term 必须连续,也不要求顺序相邻。

如果要查连续短语,应该使用 match_phrase


十二、match 查询适合什么字段

match 最适合:

  • text 字段
  • 标题
  • 正文
  • 摘要
  • 评论
  • 用户输入的关键词搜索

不太适合:

  • ID
  • 状态
  • 分类
  • 是否启用
  • 枚举值

这些结构化字段更适合用 termterms


十三、match 查询 keyword 字段会怎样

如果对 keyword 字段使用 match,并不是一定不能用,但它通常会退化成接近精确匹配的效果。

例如:

POST article_search/_search
{
  "query": {
    "match": {
      "category": "elasticsearch"
    }
  }
}

因为 categorykeyword,不会像正文那样分词,所以这个查询通常能命中 category 正好是 elasticsearch 的文档。

但是工程上更推荐写成:

POST article_search/_search
{
  "query": {
    "term": {
      "category": "elasticsearch"
    }
  }
}

原因是语义更清楚:

  • match:全文检索
  • term:精确词项匹配

十四、常见误区

1. match 不是模糊包含

match 不是 SQL 里的:

LIKE '%关键词%'

它依赖的是 analyzer 产生的 term。

如果某个词没有以合适的 term 进入倒排索引,match 也不一定能搜到。


2. match 不是精确匹配

查询:

{
  "match": {
    "content": "ElasticSearch 倒排索引"
  }
}

不代表必须完整包含这句话。

它通常会分析成多个 term,再根据匹配情况计算相关性。

如果要查固定短语,更适合用 match_phrase


3. 中文搜索效果主要看分词

中文搜索中,很多问题不是 match 写错了,而是 analyzer 不合适。

排查顺序建议是:

  1. _analyze 看字段分词结果
  2. 确认索引时和搜索时 analyzer 是否符合预期
  3. 再调整 match 的参数

十五、一句话总结

match 是全文检索的主力查询。

它适合用户输入关键词后搜索标题、正文这类 text 字段。

记住一句话:

match 会先分析查询文本,再用分析后的 term 去倒排索引中查找,并根据相关性评分返回结果。


参考链接

在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐