在查询时覆盖字段值
如果你创建一个与映射中已存在的字段同名的运行时字段,该运行时字段会遮蔽原有的映射字段。在查询时,Elasticsearch 会评估该运行时字段,根据脚本计算出一个值,并将该值作为查询的一部分返回。由于运行时字段遮蔽了映射字段,你可以在不修改映射字段的情况下覆盖搜索返回的值。
例如,假设你将以下文档索引到了 my-index-000001 中
POST my-index-000001/_bulk?refresh=true
{"index":{}}
{"@timestamp":1516729294000,"model_number":"QVKC92Q","measures":{"voltage":5.2}}
{"index":{}}
{"@timestamp":1516642894000,"model_number":"QVKC92Q","measures":{"voltage":5.8}}
{"index":{}}
{"@timestamp":1516556494000,"model_number":"QVKC92Q","measures":{"voltage":5.1}}
{"index":{}}
{"@timestamp":1516470094000,"model_number":"QVKC92Q","measures":{"voltage":5.6}}
{"index":{}}
{"@timestamp":1516383694000,"model_number":"HG537PU","measures":{"voltage":4.2}}
{"index":{}}
{"@timestamp":1516297294000,"model_number":"HG537PU","measures":{"voltage":4.0}}
后来你发现 HG537PU 传感器上报的电压值并非真实值。索引值应该比上报的值高 1.7 倍!无需对数据进行重建索引,你可以在 _search 请求的 runtime_mappings 部分定义一个脚本,以遮蔽 voltage 字段并在查询时计算出新值。
如果你搜索型号匹配 HG537PU 的文档
GET my-index-000001/_search
{
"query": {
"match": {
"model_number": "HG537PU"
}
}
}
响应包含了匹配型号 HG537PU 的文档的已索引值
{
...
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0296195,
"hits" : [
{
"_index" : "my-index-000001",
"_id" : "F1BeSXYBg_szTodcYCmk",
"_score" : 1.0296195,
"_source" : {
"@timestamp" : 1516383694000,
"model_number" : "HG537PU",
"measures" : {
"voltage" : 4.2
}
}
},
{
"_index" : "my-index-000001",
"_id" : "l02aSXYBkpNf6QRDO62Q",
"_score" : 1.0296195,
"_source" : {
"@timestamp" : 1516297294000,
"model_number" : "HG537PU",
"measures" : {
"voltage" : 4.0
}
}
}
]
}
}
以下请求定义了一个运行时字段,其中脚本会对 model_number 值为 HG537PU 的字段进行评估。对于每个匹配项,脚本会将 voltage 字段的值乘以 1.7。
使用 _search API 上的 fields 参数,你可以检索搜索请求中匹配的文档里 measures.voltage 字段的脚本计算值
POST my-index-000001/_search
{
"runtime_mappings": {
"measures.voltage": {
"type": "double",
"script": {
"source":
"""if (doc['model_number.keyword'].value.equals('HG537PU'))
{emit(1.7 * params._source['measures']['voltage']);}
else{emit(params._source['measures']['voltage']);}"""
}
}
},
"query": {
"match": {
"model_number": "HG537PU"
}
},
"fields": ["measures.voltage"]
}
查看响应,每个结果中 measures.voltage 的计算值分别为 7.14 和 6.8。这才是正确的数值!运行时字段在搜索请求中计算出了该值,而没有修改已映射的值,该值仍会在响应中返回
{
...
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.0296195,
"hits" : [
{
"_index" : "my-index-000001",
"_id" : "F1BeSXYBg_szTodcYCmk",
"_score" : 1.0296195,
"_source" : {
"@timestamp" : 1516383694000,
"model_number" : "HG537PU",
"measures" : {
"voltage" : 4.2
}
},
"fields" : {
"measures.voltage" : [
7.14
]
}
},
{
"_index" : "my-index-000001",
"_id" : "l02aSXYBkpNf6QRDO62Q",
"_score" : 1.0296195,
"_source" : {
"@timestamp" : 1516297294000,
"model_number" : "HG537PU",
"measures" : {
"voltage" : 4.0
}
},
"fields" : {
"measures.voltage" : [
6.8
]
}
}
]
}
}