term 与 range 是什么
term 是精确值匹配,range 是范围匹配,两者是 Elasticsearch 查询里出现频率最高的原子条件。term 不做分词,因此字段类型决定结果:对 text 字段用 term 往往查不到,因为存储的是分词后的词条,要用 keyword 子字段或改写成 match 查询。range 支持数值、日期与字符串区间,时间条件可以直接写相对表达式。
基本信息
| 适用引擎 | Elasticsearch 7.x / 8.x,DSL 语法基本一致 |
|---|---|
| term 语义 | 精确匹配,不分词 |
| range 适用类型 | 数值、日期、字符串(按字典序) |
| 多值写法 | terms 一次匹配多个精确值,比多个 term 更简洁 |
典型使用场景
- 日志过滤:按级别精确匹配只看错误级别日志
- 耗时筛选:按 duration 区间找出慢请求
- 时间窗口:限定时间范围拉取某次故障期间的文档
- 状态码集合:一次匹配多个错误状态码
- 多条件组合:在 bool 查询里用 term 与 range 混合过滤
- 口径核对:用范围查询抽查某字段的取值分布是否落在预期区间
查询示例
查询示例
# term:精确匹配 keyword 字段
GET /logs-app/_search {"query": {"term": {"level.keyword": "error"}}}
# terms:一次匹配多个精确值
GET /logs-app/_search {"query": {"terms": {"level.keyword": ["error", "warn"]}}}
# range:数值区间
GET /logs-app/_search {"query": {"range": {"duration_ms": {"gte": 1000, "lt": 5000}}}}
# range:时间区间,支持相对表达式
GET /logs-app/_search {"query": {"range": {"@timestamp": {"gte": "now-1h"}}}}
# 组合:错误级别且耗时超过 1 秒
GET /logs-app/_search {"query": {"bool": {"filter": [{"term": {"level.keyword": "error"}}, {"range": {"duration_ms": {"gte": 1000}}}]}}}参数与语义
| 写法 | 含义 | 注意 |
|---|---|---|
| term | 单值精确匹配 | text 字段上不生效,改用 keyword |
| terms | 多值精确匹配 | 值数量过多时性能下降 |
| range 的 gte / gt | 大于等于 / 大于 | 边界是否包含要明确 |
| range 的 lte / lt | 小于等于 / 小于 | 与告警口径保持一致 |
| 时间表达式 | now-1h 等相对写法 | 服务端按请求时刻解析 |
| match | 分词后匹配,非精确 | 需要模糊匹配时用它而不是 term |
过滤型条件放在 bool 查询的 filter 子句里可以利用缓存、不参与评分,日志检索场景下比 must 更合适。
字段类型决定查询行为:写入时把数值存成字符串,后续范围查询会按字典序比较,出现「9 比 10 大」这类错误结果。
字段名写错或后缀不对时的典型表现是命中数为零而不是报错,先用一条最小查询确认字段确实存在,再往上叠条件。