深入学习 ElasticSearch 的搜索(四):term 查询
深入学习 ElasticSearch 的搜索(四):term 查询
term 查询用于精确词项匹配。
它和 match 最大的区别是:
match 会分析查询文本,term 不会按全文检索方式分析查询文本。
所以 term 更适合查结构化字段,例如分类、状态、标签、用户 ID、订单号等。
一、基本写法
查询分类是 elasticsearch 的文章:
POST article_search/_search
{
"query": {
"term": {
"category": "elasticsearch"
}
}
}
这里的 category 是 keyword 字段。
写入什么值,倒排索引里基本就是什么 term。
因此 term 查询可以精确命中。
二、term 查询适合 keyword 字段
例如 mapping 中:
{
"category": {
"type": "keyword"
},
"status": {
"type": "keyword"
},
"author": {
"type": "keyword"
}
}
这些字段一般不需要分词。
查询时也通常不希望它被分析。
例如:
POST article_search/_search
{
"query": {
"term": {
"status": "published"
}
}
}
这个查询表达的是:
只查状态精确等于 published 的文档。
三、term 查询 text 字段为什么容易查不到
这是初学者最常见的问题。
假设 title 是 text 字段,写入:
ElasticSearch 入门教程
索引时,字段会经过 analyzer,可能进入倒排索引的 term 是:
elasticsearch
入
门
教
程
这时如果查询:
POST article_search/_search
{
"query": {
"term": {
"title": "ElasticSearch"
}
}
}
可能查不到。
原因是 term 不会把查询值自动分析成 elasticsearch。
它会直接用 ElasticSearch 这个精确值去查倒排索引。
但倒排索引里实际可能是小写的:
elasticsearch
所以没有命中。
四、如果要查 text 字段,用 match
对于标题和正文这类 text 字段,一般使用:
POST article_search/_search
{
"query": {
"match": {
"title": "ElasticSearch"
}
}
}
match 会分析查询文本,因此更适合全文检索。
记住:
text 字段 + 用户关键词搜索 -> match
keyword 字段 + 精确值过滤 -> term
五、terms:多个精确值匹配
如果要查询多个分类,可以使用 terms。
POST article_search/_search
{
"query": {
"terms": {
"category": ["elasticsearch", "redis"]
}
}
}
含义是:
category 是 elasticsearch 或 redis 的文档都返回。
这类似 SQL 中的:
WHERE category IN ('elasticsearch', 'redis')
要注意:
terms的默认语义是“命中任意一个”,更像 SQL 的IN,不是多个term的 AND 组合。
所以它没有 operator: "and" 这种参数。
如果业务要求“必须同时包含多个值”,应该考虑:
bool.must中放多个termterms_set
例如要求 entity_names 同时包含 张三丰 和 郭靖:
POST article_search/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"entity_names": "张三丰"
}
},
{
"term": {
"entity_names": "郭靖"
}
}
]
}
}
}
六、exists:判断字段是否存在
exists 用于判断某个字段是否有值。
POST article_search/_search
{
"query": {
"exists": {
"field": "created_at"
}
}
}
如果要查某个字段不存在,可以放到 must_not 中:
POST article_search/_search
{
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "created_at"
}
}
]
}
}
}
它适合:
- 查缺失字段
- 过滤字段不为空的数据
- 做数据质量排查
七、range:数字和日期范围
range 用于范围查询。
它不是查“等于某个值”,而是查字段是否落在某个区间内。
查询浏览量大于 100 的文章:
POST article_search/_search
{
"query": {
"range": {
"views": {
"gt": 100
}
}
}
}
查询某个时间范围内的文章:
POST article_search/_search
{
"query": {
"range": {
"created_at": {
"gte": "2026-04-01",
"lte": "2026-04-30"
}
}
}
}
四个常见边界参数:
gt:大于gte:大于等于lt:小于lte:小于等于
可以简单理解:
term:查一个离散值terms:查多个离散值range:查一个连续区间
八、term 查询也会出现在 filter 中
在实际业务中,term 常常和 bool.filter 一起使用。
例如查询正文包含 ElasticSearch,并且状态是 published:
POST article_search/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"content": "ElasticSearch"
}
}
],
"filter": [
{
"term": {
"status": "published"
}
}
]
}
}
}
这里:
match负责全文检索,并参与评分term负责状态过滤,不参与评分
这是一种非常常见的组合。
九、term 查询和大小写
term 是精确词项查询,所以大小写很重要。
如果 keyword 字段中存的是:
Published
查询:
{
"term": {
"status": "published"
}
}
就可能查不到。
解决方式通常有几种:
- 写入时统一小写
- 查询时统一小写
- 使用 normalizer 处理 keyword 字段
对于分类、状态、枚举值,建议从数据设计阶段就统一格式。
十、term 查询适合什么场景
适合:
- 分类
- 状态
- 标签
- 用户 ID
- 订单号
- 枚举值
- 是否启用
- 已抽取的人名实体,例如
entity_names
不适合:
- 文章正文全文搜索
- 标题关键词搜索
- 用户自然语言输入
十一、常见误区
1. term 不是全文搜索
term 不会像 match 一样分析查询文本。
所以不要用它来做普通关键词搜索。
2. term 查询 text 字段要非常小心
不是绝对不能查 text 字段,而是你必须知道该字段最终进入倒排索引的 term 是什么。
如果不知道,先用:
POST article_search/_analyze
{
"field": "title",
"text": "ElasticSearch 入门教程"
}
看清楚分词结果再判断。
3. keyword 字段不是不能用 match,但 term 更清楚
对 keyword 字段使用 match 有时也能命中。
但工程上更推荐用 term,因为语义明确,别人一看就知道这是精确匹配。
十二、一句话总结
term 查询用于精确词项匹配。
最重要的使用原则是:
查 text 字段的自然语言内容,用 match;查 keyword 字段的精确值,用 term。
参考链接
-
Term query
https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-term-query -
Keyword field type
https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/keyword -
Exists query
https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-exists-query -
Range query
https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-range-query

更多推荐




所有评论(0)