クエリ時にフィールド値をオーバーライドする
マッピングに既に存在するフィールドと同じ名前のランタイムフィールドを作成すると、ランタイムフィールドはマッピングされたフィールドを隠します。クエリ時に、Elasticsearchはランタイムフィールドを評価し、スクリプトに基づいて値を計算し、その値をクエリの一部として返します。ランタイムフィールドがマッピングされたフィールドを隠すため、マッピングされたフィールドを変更することなく、検索で返される値をオーバーライドできます。
例えば、次のドキュメントを my-index-000001
にインデックスしたとしましょう:
Python
resp = client.bulk(
index="my-index-000001",
refresh=True,
operations=[
{
"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
}
}
],
)
print(resp)
Ruby
response = client.bulk(
index: 'my-index-000001',
refresh: true,
body: [
{
index: {}
},
{
"@timestamp": 1_516_729_294_000,
model_number: 'QVKC92Q',
measures: {
voltage: 5.2
}
},
{
index: {}
},
{
"@timestamp": 1_516_642_894_000,
model_number: 'QVKC92Q',
measures: {
voltage: 5.8
}
},
{
index: {}
},
{
"@timestamp": 1_516_556_494_000,
model_number: 'QVKC92Q',
measures: {
voltage: 5.1
}
},
{
index: {}
},
{
"@timestamp": 1_516_470_094_000,
model_number: 'QVKC92Q',
measures: {
voltage: 5.6
}
},
{
index: {}
},
{
"@timestamp": 1_516_383_694_000,
model_number: 'HG537PU',
measures: {
voltage: 4.2
}
},
{
index: {}
},
{
"@timestamp": 1_516_297_294_000,
model_number: 'HG537PU',
measures: {
voltage: 4
}
}
]
)
puts response
Js
const response = await client.bulk({
index: "my-index-000001",
refresh: "true",
operations: [
{
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,
},
},
],
});
console.log(response);
コンソール
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
に一致するドキュメントを検索する場合:
Python
resp = client.search(
index="my-index-000001",
query={
"match": {
"model_number": "HG537PU"
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
query: {
match: {
model_number: 'HG537PU'
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
query: {
match: {
model_number: "HG537PU",
},
},
});
console.log(response);
コンソール
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
で乗算します。
fields
パラメータを _search
API で使用すると、検索リクエストに一致するドキュメントの measures.voltage
フィールドに対してスクリプトが計算した値を取得できます:
Python
resp = client.search(
index="my-index-000001",
runtime_mappings={
"measures.voltage": {
"type": "double",
"script": {
"source": "if (doc['model_number.keyword'].value.equals('HG537PU'))\n {emit(1.7 * params._source['measures']['voltage']);}\n else{emit(params._source['measures']['voltage']);}"
}
}
},
query={
"match": {
"model_number": "HG537PU"
}
},
fields=[
"measures.voltage"
],
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
runtime_mappings: {
'measures.voltage' => {
type: 'double',
script: {
source: "if (doc['model_number.keyword'].value.equals('HG537PU'))\n {emit(1.7 * params._source['measures']['voltage']);}\n else{emit(params._source['measures']['voltage']);}"
}
}
},
query: {
match: {
model_number: 'HG537PU'
}
},
fields: [
'measures.voltage'
]
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
runtime_mappings: {
"measures.voltage": {
type: "double",
script: {
source:
"if (doc['model_number.keyword'].value.equals('HG537PU'))\n {emit(1.7 * params._source['measures']['voltage']);}\n else{emit(params._source['measures']['voltage']);}",
},
},
},
query: {
match: {
model_number: "HG537PU",
},
},
fields: ["measures.voltage"],
});
console.log(response);
コンソール
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
]
}
}
]
}
}