首页/数据/NoSQL 速查/term 精确查询
Elasticsearch89 条

term 精确查询

term 对字段值做精确匹配且不对查询串分词:keyword 字段匹配整串,数值与布尔直接比较;对 text 字段则匹配分词后的单个词条。

NoSQL 速查数据更新于 2026-10-13

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 都不做分词,能否命中取决于写入时该字段是否按同样的整串形式索引,字段类型与写入值的形态要一起核对。

易错点

  • 对 text 字段用 term 查整句通常无命中:写入时已被拆词,term 查的是单个词条
  • terms 数组元素类型要与字段一致,字符串数字与数值类型不互通,容易静默无命中
  • 拿 term 当模糊查询用会误判结果,前缀与子串匹配需要换查询类型
  • case_insensitive 只对 keyword 类字段生效,对 text 字段设置它没有任何作用
  • 把精确过滤条件写在 must 里会白算评分,纯筛选应放进 filter 子句

数据来源与参考

  • Elasticsearch Guide: Term query
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌