term 查询是什么
term 查询对字段值做精确匹配且不对查询串做分析:keyword 字段匹配整个字符串,数值与布尔直接比较,对 text 字段则匹配分词后的单个词条。terms 是它的多值版本,任意一个命中即算匹配。它默认不参与相关性评分,常用于状态、ID、标签这类枚举值的过滤,放进 filter 子句还能复用过滤器缓存。
基本信息
| 查询类型 | term(单值)/ terms(多值任一命中) |
|---|---|
| 匹配语义 | 查询词不做分析,直接查索引词条 |
| 附加选项 | case_insensitive(仅 keyword 类字段)、boost |
| 适用字段 | keyword、数值、布尔、ip |
| 评分 | 默认不评分,适合放 filter 子句 |
| 适用版本 | Elasticsearch 7.x / 8.x |
典型使用场景
- 按状态、类型等枚举字段做精确过滤
- 按用户 ID、订单号取文档,替代全文检索
- 多值筛选:terms 一次筛多个标签或渠道
- 多租户隔离:按租户标识过滤,可复用查询缓存
- 数值范围之外的精确匹配,例如版本号或等级
- 组合到 bool 的 filter 里做权限与可见性控制
示例
示例
GET /my-index/_search
{
"query": {
"term": { "user.id": { "value": "kimchy", "case_insensitive": true } } # keyword 忽略大小写
}
}
GET /my-index/_search
{
"query": { "terms": { "status": ["open", "pending"] } } # 多值任一命中
}
GET /my-index/_search
{
"query": { "bool": { "filter": [ { "term": { "tenant": "t-1024" } } ] } } # 放 filter 可缓存
}相关查询对照
| 查询 | 是否分词 | 适用字段与场景 |
|---|---|---|
| term | 不分词 | keyword、数值、布尔精确匹配 |
| terms | 不分词 | 多值任一命中,批量筛选 |
| match | 分词 | text 字段的全文检索 |
| prefix | 不分词 | keyword 前缀匹配,慎用于高基数 |
| wildcard | 不分词 | 通配匹配,代价高,避免前导通配 |
| exists | 不适用 | 判断字段是否存在 |
要按前缀或子串模糊匹配应使用 prefix、wildcard 或 match 查询,term 只做整串/整词条的精确匹配,不承担模糊能力。
term 放在 filter 子句里不参与评分,条件不变时结果可被缓存;把它写在 must 里会白算评分,属于常见的低级性能损耗。
前导通配(如 *abc)与高基数 keyword 上的 wildcard 查询会扫描大量词条,线上慎用;能改成 keyword 精确匹配或加前缀字段就不要用通配。
精确匹配实践要点
- 枚举字段用 keyword 类型,term 才能按整串命中
- 高基数字段上的 term 查询要确认索引存在,否则退化为全扫描
- terms 列表不宜过长,几百个以上考虑拆批或改成布尔组合
- 把 term 放进 filter 可缓存结果,重复查询更快
- 大小写是否敏感在写入时就已定型,查询期改不了分词行为
- 数值字段做 term 匹配时注意类型一致,字符串与数值不互通
无命中排查顺序
- 先确认字段类型是 keyword 还是 text
- 用 _analyze 看该字段实际被索引成哪些词条
- 核对查询值与写入值是否完全一致(大小写、前后空格)
- 检查字段名是否写错,或误用了不存在的子字段
- 确认查询值类型与字段映射一致
- 用 exists 查询先确认该字段确实有值
多值筛选与组合
多值筛选与组合
GET /my-index/_search
{ "query": { "bool": { "filter": [ { "terms": { "tag": ["a", "b"] } }, { "term": { "tenant": "t-1" } } ] } } }
GET /my-index/_search
{ "query": { "bool": { "must_not": [ { "term": { "flag": "deleted" } } ] } } }terms 的取值列表很长时会占用较多查询体与内存,几百个以上建议拆批或用布尔组合;超长列表可考虑在写入期预计算一个筛选标记字段。
常见误用
- 拿 term 去查 text 字段的整句,结果永远为空
- 把字符串数字与数值字段互相比较,命中数与预期不符
- 在高基数 keyword 字段上用 wildcard,查询会打满 CPU
- 该放 filter 的精确过滤条件写进了 must,白算评分
- 误以为 case_insensitive 对 text 字段有效,实际毫无作用
- terms 一次传几百个值,查询体过大导致超时或被拒绝
term 与 terms 都不做分词,能否命中取决于写入时该字段是否按同样的整串形式索引,字段类型与写入值的形态要一起核对。