Term Query 和 Match Query 的区别是什么?
在 Elasticsearch (ES) 中,Term Query 和 Match Query 是最常用的两种查询方式,它们的核心区别在于 是否对查询语句进行分词(Analysis)。
简单总结:
- Term Query:精确匹配。搜索前不对搜索词进行分词,直接去倒排索引中查找完全一致的词。
- Match Query:全文检索。搜索前会对搜索词进行分词,然后去匹配分词后的结果。
详细对比
1. 处理机制 (Processing Mechanism)
Term Query (词条查询):
- 它将你输入的查询内容看作一个整体。
- 它不会经过分析器(Analyzer)处理(即不会变小写、不会去除停用词、不会拆词)。
- 它直接在倒排索引(Inverted Index)中查找与输入内容完全字节级匹配的词项。
- 类比:类似于编程语言中的
==或 SQL 中的=。
Match Query (匹配查询):
- 它是一个高级查询。
- 它会先使用该字段配置的分析器(Analyzer)对你的查询语句进行分词处理。
- 例如:输入 "Hello World",标准分析器会将其拆分为 "hello" 和 "world" 两个词,然后去索引中查找包含这两个词(或其中之一,取决于 operator)的文档。
- 类比:类似于 Google 搜索或 SQL 中的
LIKE(但更智能)。
2. 适用场景 (Use Cases)
Term Query 适合查:
- 结构化数据。
- 枚举值(状态码、标签)。
- ID、GUID。
- 日期、数字、布尔值。
- Keyword 类型的字段(不分词的文本)。
Match Query 适合查:
- 非结构化文本(全文搜索)。
- 文章标题、内容描述、评论。
- Text 类型的字段(经过分词的文本)。
3. 字段类型对应 (Field Types)
这是最容易踩坑的地方:
针对
keyword类型字段:- 数据存储时原样存储(如 "Apple" 存为 "Apple")。
- 使用
Term Query搜索 "Apple" -> 匹配。 - 使用
Term Query搜索 "apple" -> 不匹配(大小写敏感)。
针对
text类型字段:- 数据存储时会被分词器处理(默认标准分词器会将 "Apple" 转为小写 "apple" 并存入索引)。
- 使用
Term Query搜索 "Apple" -> 不匹配(因为索引里只有 "apple",而 Term 拿着 "Apple" 去找,找不到)。 - 使用
Match Query搜索 "Apple" -> 匹配(因为 Match 会先把 "Apple" 变成 "apple",然后去索引里找 "apple")。
举例说明 (The "Aha!" Moment)
假设索引中有一条文档:
json
{
"id": 1,
"title": "Quick Brown Fox"
}
假设 title 字段的类型是 text(使用默认 Standard Analyzer,索引中实际存储的是 quick, brown, fox)。
场景 A:使用 Term Query
json
GET /_search
{
"query": {
"term": {
"title": "Quick"
}
}
}
- 结果:无匹配。
- 原因:
term不处理查询词,直接拿 "Quick" 去找。但索引里只有小写的 "quick"。
场景 B:使用 Term Query (查小写)
json
GET /_search
{
"query": {
"term": {
"title": "quick"
}
}
}
- 结果:匹配。
- 原因:索引里确实有 "quick"。
场景 C:使用 Match Query
json
GET /_search
{
"query": {
"match": {
"title": "Quick Brown"
}
}
}
- 结果:匹配。
- 原因:
match会先分析 "Quick Brown" -> 变成 "quick" 和 "brown"。然后去索引找,发现都能找到。
总结表
| 特性 | Term Query | Match Query |
|---|---|---|
| 分词处理 | 不分词 (原样搜索) | 分词 (先分析再搜索) |
| 匹配方式 | 精确匹配 (Exact Match) | 全文检索 / 模糊匹配 |
| 大小写敏感 | 是 (除非索引本身已转小写) | 否 (通常分析器会转小写) |
| 适用字段类型 | keyword, integer, date, boolean |
text |
| 计算开销 | 极低 (直接查倒排表) | 稍高 (需分词和算分) |
| 常见用途 | 过滤状态、ID查找、聚合统计 | 搜索文章、模糊查找 |
最佳实践建议
- 如果你要查的是 "ID"、"状态"、"分类" -> 用 Term。
- 如果你要查的是 "用户输入的一段话" -> 用 Match。
- 新手巨坑:不要对
text类型的字段使用term查询,除非你非常清楚分词后的结果是什么(通常是全小写)。如果需要对文本字段既做全文搜又做精确配,请使用fields多字段映射(一个字段同时拥有text和keyword属性)。