runtime 字段是什么
runtime 字段在查询时计算,不占索引空间:既可以在查询请求里用 runtime_mappings 临时定义,也可以写进索引映射长期生效。它适合对已有数据做探索性统计,比如从复合字段里拆出值、按时间派生星期与时段、给旧索引补一个原本没有的字段,而不用先重建索引。
能用的同时要算成本
runtime 字段可以被搜索、聚合与排序,行为与普通字段一致,前提是脚本输出的类型与声明的 type 匹配。代价是每次查询都按需计算:命中量大或把它当常用过滤条件时,成本会持续发生。统计口径确认稳定后,应该把它固化进映射或直接物化成真实字段。
基本信息
| 定义位置 | 查询请求的 runtime_mappings,或映射里的 runtime 段 |
|---|---|
| 常见类型 | keyword、long、double、date 等 |
| 输出方式 | 脚本里用 emit() 输出值 |
| 典型用途 | 拆复合字段、派生时间维度、给旧索引补字段 |
| 适用版本 | Elasticsearch 7.11 起提供 |
示例
示例
GET /logs/_search
{
"size": 0,
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": { "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))" }
}
},
"aggs": { "by_day": { "terms": { "field": "day_of_week" } } }
}
# 固化到映射:之后所有查询都能直接用这个字段
PUT /logs/_mapping
{ "runtime": { "day_of_week": { "type": "keyword", "script": { "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))" } } } }典型使用场景
- 探索性统计:不重建索引就试算新维度
- 拆字段:把组合值拆成可聚合的独立维度
- 时间派生:从时间戳算出星期、小时段、是否工作日
- 旧索引补字段:历史数据无法回填时用 runtime 顶替
- 灰度验证:先确认口径正确,再决定是否物化成真实字段
要素与注意
| 要素 | 含义 | 注意 |
|---|---|---|
| runtime_mappings | 请求级定义,只对本次查询生效 | 适合临时探索 |
| 映射 runtime 段 | 长期生效,所有查询可见 | 改动后对后续查询立即生效 |
| emit() | 脚本输出值的入口 | 类型与声明不符会丢值 |
| type | 字段类型 | 决定能否聚合、排序以及按什么方式比较 |
脚本类型与 emit 输出不匹配会静默丢值,聚合前先用简单查询验证字段确实有输出,再上聚合,避免对着一堆空桶排查。
把 runtime 字段当常用过滤条件会持续承担计算成本,高频使用的字段应常规索引;在大量文档上跑复杂脚本会明显拖慢查询。