索引一个运行时字段
运行时字段定义在它们运行的上下文。例如,你可以在一个 搜索请求上下文里或者在一个索引映射的 runtime 部分里定义运行时字段。如果你决定为了更好的性能索引一个运行时字段,只需要移动整个的运行时字段定义(包括脚本)到一个索引映射的上下文中。Elasticsearch 自动使用这些索引后的字段驱动查询,结果是会有一个很快的响应时间。这个能力意味着你只需要写一次脚本,然后可以把它应用到任何支持运行时字段的上下文。
🏳️ 目前还不支持索引一个
composite运行时字段
然后你可以使用运行时字段来限制 ES 需要进行值计算的字段的数量。使用索引字段串联运行时字段在你索引的数据里和如何为其它字段定义查询上能提供足够的弹性。
索引一个运行时字段后,你将不能再更新里面包含的脚本。如果你想改变脚本,那么创建一个包含更新后脚本的新字段。
例如,假设你的公司想要替换一些旧的压力值。连接的传感器只能报告一小部分真实读数。与其装备新的传感器获取压力值,你不如决定基于报告的读数计算出值。基于报告的数据,你为 my-index-000001 映射里定义了下面的字段:
PUT my-index-000001/
{
"mappings": {
"properties": {
"timestamp": {
"type": "date"
},
"temperature": {
"type": "long"
},
"voltage": {
"type": "double"
},
"node": {
"type": "keyword"
}
}
}
}
然后你批量索引一些传感器的示例数据。数据包括每一个传感器的 voltage 读数:
POST my-index-000001/_bulk?refresh=true
{"index":{}}
{"timestamp": 1516729294000, "temperature": 200, "voltage": 5.2, "node": "a"}
{"index":{}}
{"timestamp": 1516642894000, "temperature": 201, "voltage": 5.8, "node": "b"}
{"index":{}}
{"timestamp": 1516556494000, "temperature": 202, "voltage": 5.1, "node": "a"}
{"index":{}}
{"timestamp": 1516470094000, "temperature": 198, "voltage": 5.6, "node": "b"}
{"index":{}}
{"timestamp": 1516383694000, "temperature": 200, "voltage": 4.2, "node": "c"}
{"index":{}}
{"timestamp": 1516297294000, "temperature": 202, "voltage": 4.0, "node": "c"}
告诉了一些网站工程师之后,你意识到传感器至少应该报告现在值的两倍,可能还不止。你创建了一个 voltage_corrected 运行时字段检索出当前的电压并将它乘以 2:
PUT my-index-000001/_mapping
{
"runtime": {
"voltage_corrected": {
"type": "double",
"script": {
"source": """
emit(doc['voltage'].value * params['multiplier'])
""",
"params": {
"multiplier": 2
}
}
}
}
}
你通过 _search API 上的 fields参数检索计算后的值:
GET my-index-000001/_search
{
"fields": [
"voltage_corrected",
"node"
],
"size": 2
}
当审查了传感器数据并运行了一些测试后,你查明报告传感器数据的乘数应该是 4。为了获得更好的性能,你决定使用新的 multiplier 参数索引 voltage_corrected 运行时字段。
在一个名为 my-index-000001 的新索引里,复制 voltage_corrected 运行时字段的定义到新索引的映射里。就这么简单!你可以添加一个名为 on_script_error 的附加参数,这个参数可以决定如果在索引时脚本抛出了一个错误是否要拒绝掉整个的文档(默认拒绝)。
PUT my-index-000001/
{
"mappings": {
"properties": {
"timestamp": {
"type": "date"
},
"temperature": {
"type": "long"
},
"voltage": {
"type": "double"
},
"node": {
"type": "keyword"
},
"voltage_corrected": {
"type": "double",
"on_script_error": "fail", // @1
"script": {
"source": """
emit(doc['voltage'].value * params['multiplier'])
""",
"params": {
"multiplier": 4
}
}
}
}
}
}
@1:如果在索引时脚本抛出了一个错误,整个文档会被拒绝。设置值为
ignore的话将会把字段注册到文档的_ignored元数据并且索引会继续。
批量索引一些传感器的示例数据到 my-index-000001 索引:
POST my-index-000001/_bulk?refresh=true
{ "index": {}}
{ "timestamp": 1516729294000, "temperature": 200, "voltage": 5.2, "node": "a"}
{ "index": {}}
{ "timestamp": 1516642894000, "temperature": 201, "voltage": 5.8, "node": "b"}
{ "index": {}}
{ "timestamp": 1516556494000, "temperature": 202, "voltage": 5.1, "node": "a"}
{ "index": {}}
{ "timestamp": 1516470094000, "temperature": 198, "voltage": 5.6, "node": "b"}
{ "index": {}}
{ "timestamp": 1516383694000, "temperature": 200, "voltage": 4.2, "node": "c"}
{ "index": {}}
{ "timestamp": 1516297294000, "temperature": 202, "voltage": 4.0, "node": "c"}
现在你可以在一个搜索查询里检索计算后的值,并且可以基于精确的值来查找文档。下面的范围查询将返回 voltage_corrected 计算后的值大于或等于16且小于等于20的所有文档。再一次,使用 _search API 上的 fields参数检索出你想要的字段:
POST my-index-000001/_search
{
"query": {
"range": {
"voltage_corrected": {
"gte": 16,
"lte": 20,
"boost": 1.0
}
}
},
"fields": ["voltage_corrected", "node"]
}
响应包含了匹配到范围查询的文档的 voltage_corrected 字段,基于包含的脚本计算后的值:
{
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my-index-000001",
"_id" : "yoSLrHgBdg9xpPrUZz_P",
"_score" : 1.0,
"_source" : {
"timestamp" : 1516383694000,
"temperature" : 200,
"voltage" : 4.2,
"node" : "c"
},
"fields" : {
"voltage_corrected" : [
16.8
],
"node" : [
"c"
]
}
},
{
"_index" : "my-index-000001",
"_id" : "y4SLrHgBdg9xpPrUZz_P",
"_score" : 1.0,
"_source" : {
"timestamp" : 1516297294000,
"temperature" : 202,
"voltage" : 4.0,
"node" : "c"
},
"fields" : {
"voltage_corrected" : [
16.0
],
"node" : [
"c"
]
}
}
]
}
}