検索リクエストでのランタイムフィールドの定義
検索リクエストで runtime_mappings
セクションを指定することで、クエリの一部としてのみ存在するランタイムフィールドを作成できます。スクリプトは runtime_mappings
セクションの一部として指定しますが、これは マッピングにランタイムフィールドを追加する場合 と同様です。
検索リクエストでランタイムフィールドを定義することは、インデックスマッピングでランタイムフィールドを定義するのと同じ形式を使用します。インデックスマッピングの runtime
からフィールド定義をコピーして、検索リクエストの runtime_mappings
セクションに貼り付けます。
次の検索リクエストは、day_of_week
フィールドを runtime_mappings
セクションに追加します。フィールド値は動的に計算され、この検索リクエストのコンテキスト内でのみ計算されます:
Python
resp = client.search(
index="my-index-000001",
runtime_mappings={
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
}
}
},
aggs={
"day_of_week": {
"terms": {
"field": "day_of_week"
}
}
},
)
print(resp)
Js
const response = await client.search({
index: "my-index-000001",
runtime_mappings: {
day_of_week: {
type: "keyword",
script: {
source:
"emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))",
},
},
},
aggs: {
day_of_week: {
terms: {
field: "day_of_week",
},
},
},
});
console.log(response);
Console
GET my-index-000001/_search
{
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
}
}
},
"aggs": {
"day_of_week": {
"terms": {
"field": "day_of_week"
}
}
}
}
他のランタイムフィールドを使用するランタイムフィールドの作成
検索リクエストで他のランタイムフィールドから値を返すランタイムフィールドを定義することもできます。たとえば、センサーデータを一括インデックスするとしましょう:
Python
resp = client.bulk(
index="my-index-000001",
refresh=True,
operations=[
{
"index": {}
},
{
"@timestamp": 1516729294000,
"model_number": "QVKC92Q",
"measures": {
"voltage": "5.2",
"start": "300",
"end": "8675309"
}
},
{
"index": {}
},
{
"@timestamp": 1516642894000,
"model_number": "QVKC92Q",
"measures": {
"voltage": "5.8",
"start": "300",
"end": "8675309"
}
},
{
"index": {}
},
{
"@timestamp": 1516556494000,
"model_number": "QVKC92Q",
"measures": {
"voltage": "5.1",
"start": "300",
"end": "8675309"
}
},
{
"index": {}
},
{
"@timestamp": 1516470094000,
"model_number": "QVKC92Q",
"measures": {
"voltage": "5.6",
"start": "300",
"end": "8675309"
}
},
{
"index": {}
},
{
"@timestamp": 1516383694000,
"model_number": "HG537PU",
"measures": {
"voltage": "4.2",
"start": "400",
"end": "8625309"
}
},
{
"index": {}
},
{
"@timestamp": 1516297294000,
"model_number": "HG537PU",
"measures": {
"voltage": "4.0",
"start": "400",
"end": "8625309"
}
}
],
)
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',
start: '300',
end: '8675309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_642_894_000,
model_number: 'QVKC92Q',
measures: {
voltage: '5.8',
start: '300',
end: '8675309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_556_494_000,
model_number: 'QVKC92Q',
measures: {
voltage: '5.1',
start: '300',
end: '8675309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_470_094_000,
model_number: 'QVKC92Q',
measures: {
voltage: '5.6',
start: '300',
end: '8675309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_383_694_000,
model_number: 'HG537PU',
measures: {
voltage: '4.2',
start: '400',
end: '8625309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_297_294_000,
model_number: 'HG537PU',
measures: {
voltage: '4.0',
start: '400',
end: '8625309'
}
}
]
)
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",
start: "300",
end: "8675309",
},
},
{
index: {},
},
{
"@timestamp": 1516642894000,
model_number: "QVKC92Q",
measures: {
voltage: "5.8",
start: "300",
end: "8675309",
},
},
{
index: {},
},
{
"@timestamp": 1516556494000,
model_number: "QVKC92Q",
measures: {
voltage: "5.1",
start: "300",
end: "8675309",
},
},
{
index: {},
},
{
"@timestamp": 1516470094000,
model_number: "QVKC92Q",
measures: {
voltage: "5.6",
start: "300",
end: "8675309",
},
},
{
index: {},
},
{
"@timestamp": 1516383694000,
model_number: "HG537PU",
measures: {
voltage: "4.2",
start: "400",
end: "8625309",
},
},
{
index: {},
},
{
"@timestamp": 1516297294000,
model_number: "HG537PU",
measures: {
voltage: "4.0",
start: "400",
end: "8625309",
},
},
],
});
console.log(response);
Console
POST my-index-000001/_bulk?refresh=true
{"index":{}}
{"@timestamp":1516729294000,"model_number":"QVKC92Q","measures":{"voltage":"5.2","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516642894000,"model_number":"QVKC92Q","measures":{"voltage":"5.8","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516556494000,"model_number":"QVKC92Q","measures":{"voltage":"5.1","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516470094000,"model_number":"QVKC92Q","measures":{"voltage":"5.6","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516383694000,"model_number":"HG537PU","measures":{"voltage":"4.2","start": "400","end":"8625309"}}
{"index":{}}
{"@timestamp":1516297294000,"model_number":"HG537PU","measures":{"voltage":"4.0","start": "400","end":"8625309"}}
インデックス後に、数値データが text
タイプとしてマッピングされていることに気付きました。measures.start
および measures.end
フィールドで集約したいのですが、text
タイプのフィールドでは集約できないため、集約が失敗します。ランタイムフィールドが助けてくれます!インデックスフィールドと同じ名前のランタイムフィールドを追加し、データ型を変更できます:
Python
resp = client.indices.put_mapping(
index="my-index-000001",
runtime={
"measures.start": {
"type": "long"
},
"measures.end": {
"type": "long"
}
},
)
print(resp)
Ruby
response = client.indices.put_mapping(
index: 'my-index-000001',
body: {
runtime: {
'measures.start' => {
type: 'long'
},
'measures.end' => {
type: 'long'
}
}
}
)
puts response
Js
const response = await client.indices.putMapping({
index: "my-index-000001",
runtime: {
"measures.start": {
type: "long",
},
"measures.end": {
type: "long",
},
},
});
console.log(response);
Console
PUT my-index-000001/_mapping
{
"runtime": {
"measures.start": {
"type": "long"
},
"measures.end": {
"type": "long"
}
}
}
ランタイムフィールドは、インデックスマッピングで同じ名前で定義されたフィールドよりも優先されます。この柔軟性により、既存のフィールドを隠蔽し、フィールド自体を変更することなく異なる値を計算できます。インデックスマッピングに誤りがあった場合、検索リクエスト中に マッピング内の値を上書きする 値を計算するためにランタイムフィールドを使用できます。
これで、measures.start
および measures.end
フィールドに対して簡単に 平均集約 を実行できます:
Python
resp = client.search(
index="my-index-000001",
aggs={
"avg_start": {
"avg": {
"field": "measures.start"
}
},
"avg_end": {
"avg": {
"field": "measures.end"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
avg_start: {
avg: {
field: 'measures.start'
}
},
avg_end: {
avg: {
field: 'measures.end'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
aggs: {
avg_start: {
avg: {
field: "measures.start",
},
},
avg_end: {
avg: {
field: "measures.end",
},
},
},
});
console.log(response);
Console
GET my-index-000001/_search
{
"aggs": {
"avg_start": {
"avg": {
"field": "measures.start"
}
},
"avg_end": {
"avg": {
"field": "measures.end"
}
}
}
}
レスポンスには、基礎データの値を変更することなく集約結果が含まれています:
Console-Result
{
"aggregations" : {
"avg_start" : {
"value" : 333.3333333333333
},
"avg_end" : {
"value" : 8658642.333333334
}
}
}
さらに、検索クエリの一部として値を計算するランタイムフィールドを定義し、そのフィールドに対して 同じクエリ内で 統計集約 を実行できます。
duration
ランタイムフィールドはインデックスマッピングには存在しませんが、そのフィールドで検索および集約を行うことができます。次のクエリは、duration
フィールドの計算された値を返し、集約されたドキュメントから抽出された数値の統計を計算するために統計集約を実行します。
Python
resp = client.search(
index="my-index-000001",
runtime_mappings={
"duration": {
"type": "long",
"script": {
"source": "\n emit(doc['measures.end'].value - doc['measures.start'].value);\n "
}
}
},
aggs={
"duration_stats": {
"stats": {
"field": "duration"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
runtime_mappings: {
duration: {
type: 'long',
script: {
source: "\n emit(doc['measures.end'].value - doc['measures.start'].value);\n "
}
}
},
aggregations: {
duration_stats: {
stats: {
field: 'duration'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
runtime_mappings: {
duration: {
type: "long",
script: {
source:
"\n emit(doc['measures.end'].value - doc['measures.start'].value);\n ",
},
},
},
aggs: {
duration_stats: {
stats: {
field: "duration",
},
},
},
});
console.log(response);
Console
GET my-index-000001/_search
{
"runtime_mappings": {
"duration": {
"type": "long",
"script": {
"source": """
emit(doc['measures.end'].value - doc['measures.start'].value);
"""
}
}
},
"aggs": {
"duration_stats": {
"stats": {
"field": "duration"
}
}
}
}
duration
ランタイムフィールドは検索クエリのコンテキスト内にのみ存在しますが、そのフィールドで検索および集約を行うことができます。この柔軟性は非常に強力で、インデックスマッピングの誤りを修正し、単一の検索リクエスト内で動的に計算を完了することを可能にします。
Console-Result
{
"aggregations" : {
"duration_stats" : {
"count" : 6,
"min" : 8624909.0,
"max" : 8675009.0,
"avg" : 8658309.0,
"sum" : 5.1949854E7
}
}
}