映射一个运行时字段(Map a runtime field)
通过映射定义下的 runtime 部分并且定义一个无痛脚本,你可以映射运行时字段。这个脚本能访问到文档的整个上下文,包括通过 params._source 访问原始的 _source,还有任何的映射的字段和它们的值。在查询时,脚本运行并产生查询时所需要的每一个脚本化的字段的值。
发射运行时字段的值
当定义一个和运行时字段一起使用的无痛脚本时,你必须包含
emit方法来发射计算的值。
例如,下面请求里的脚本从被定义为 date 类型的 @timestamp 字段里计算一周里的星期几。这个脚本基于 timestamp 的值来计算一周里的星期几,并且使用 emit 返回计算后的值。
PUT my-index-000001/
{
"mappings": {
"runtime": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))"
}
}
},
"properties": {
"@timestamp": {"type": "date"}
}
}
}
runtime的部分可以是这些数据类型里的任何一个:
- boolean
- composite
- date
- double
- geo_point
- ip
- keyword
- long
- lookup
带有一个 date 类型的运行时字段能接收与 date 字段类型完全相同的 format 参数。
带有 lookup 类型的运行时字段允许从关联的索引检索字段。查看从关联索引检索字段。
如果动态字段映射被启用,dynamic 参数被设置为 runtime,新的字段自动作为运行时字段被添加到索引映射:
PUT my-index-000001
{
"mappings": {
"dynamic": "runtime",
"properties": {
"@timestamp": {
"type": "date"
}
}
}
}
1. 定义不带脚本的运行时字段
运行时字段通常包含一个以某些方式操纵数据的无痛脚本。然而,有时你可能定义了一个没有脚本的运行时字段的实例。例如,如果你想要从 _source 检索一个单个的字段而不去改变它,那么你不需要脚本。你可以只创建一个不带脚本的运行时字段,比如 day_of_week:
PUT my-index-000001/
{
"mappings": {
"runtime": {
"day_of_week": {
"type": "keyword"
}
}
}
}
当没有脚本被提供时,ES 在查询的时候隐式的在 _source 里寻找一个和运行时字段同名的字段,如果存在的话返回它的值。如果一个同名的字段不存在,那么响应里不包含关于运行时字段的任何值。
在大多数情况下,尽可能的通过 doc_values检索字段值。使用运行时字段访问 doc_values 比从 _source 检索值要快,因为数据是如何从 Lucene 加载的原因。
然而,有的案例有必要从 _source 检索数据。例如:text 字段默认不能从 doc_values 获得,所以你只能从 _source 里检索值。其它的实例中,你可能会选择在特定的字段上禁用 doc_values。
🏳️ 你或者可以在你想要检索值的字段前面添加上
params._source前缀(比如params._source.day_of_week)。为了简单,推荐的选项是:在任何可能的时候在映射定义里定义一个不带有脚本的运行时字段。
2. 更新和移除运行时字段
你可以在任何时候更新和移除运行时字段。要替换一个现有的运行时字段,向映射里添加一个同名的新运行时字段。要从映射里移除一个运行时字段,将这个运行时字段的值设为 null:
PUT my-index-000001/_mapping
{
"runtime": {
"day_of_week": null
}
}
下游影响
更新或移除一个运行时字段当依赖于此字段的查询运行时可能会返回不一致的结果。每一个切片会访问到脚本的不同版本,这依赖于映射改变何时生效。如果你移除或更新了运行时字段那么Kibana里依赖于这些字段的现有查询或可视化可能会失败。例如:如果一个类型为
ip的运行时字段的类型改变为boolean,或者这个运行时字段被移除了,那么使用了此字段的一个可视化的柱状图可能失败。