ランタイムフィールドのマッピング
ランタイムフィールドは、マッピング定義の下に runtime
セクションを追加し、Painless スクリプトを定義することでマッピングされます。このスクリプトは、元の _source
を params._source
経由で含むドキュメントの全コンテキストにアクセスできます。また、マッピングされたフィールドとその値にもアクセスできます。クエリ時に、スクリプトが実行され、クエリに必要な各スクリプトフィールドの値が生成されます。
ランタイムフィールド値の出力
ランタイムフィールドで使用するためのPainlessスクリプトを定義する際には、計算された値を出力するためにemit
メソッドを含める必要があります。
例えば、以下のリクエストのスクリプトは、@timestamp
フィールドから曜日を計算します。このフィールドは date
タイプとして定義されています。スクリプトは timestamp
の値に基づいて曜日を計算し、emit
を使用して計算された値を返します。
Python
resp = client.indices.create(
index="my-index-000001",
mappings={
"runtime": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
}
}
},
"properties": {
"@timestamp": {
"type": "date"
}
}
},
)
print(resp)
Js
const response = await client.indices.create({
index: "my-index-000001",
mappings: {
runtime: {
day_of_week: {
type: "keyword",
script: {
source:
"emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))",
},
},
},
properties: {
"@timestamp": {
type: "date",
},
},
},
});
console.log(response);
コンソール
PUT my-index-000001/
{
"mappings": {
"runtime": {
"day_of_week": {
"type": "keyword",
"script": {
"source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
}
}
},
"properties": {
"@timestamp": {"type": "date"}
}
}
}
runtime
セクションは、次のデータ型のいずれかであることができます:
boolean
composite
date
double
geo_point
ip
keyword
long
lookup
type
が date
のランタイムフィールドは、format
パラメータを date
フィールドタイプと同様に受け入れることができます。
type
が lookup
のランタイムフィールドは、関連インデックスからフィールドを取得することを許可します。詳細は retrieve fields from related indices
を参照してください。
dynamic
の動的フィールドマッピングが有効になっている場合、runtime
に設定されたパラメータにより、新しいフィールドがランタイムフィールドとしてインデックスマッピングに自動的に追加されます:
Python
resp = client.indices.create(
index="my-index-000001",
mappings={
"dynamic": "runtime",
"properties": {
"@timestamp": {
"type": "date"
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'my-index-000001',
body: {
mappings: {
dynamic: 'runtime',
properties: {
"@timestamp": {
type: 'date'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index-000001",
mappings: {
dynamic: "runtime",
properties: {
"@timestamp": {
type: "date",
},
},
},
});
console.log(response);
コンソール
PUT my-index-000001
{
"mappings": {
"dynamic": "runtime",
"properties": {
"@timestamp": {
"type": "date"
}
}
}
}
スクリプトなしでのランタイムフィールドの定義
ランタイムフィールドには通常、データを何らかの方法で操作するPainlessスクリプトが含まれます。しかし、スクリプトなしでランタイムフィールドを定義する場合もあります。例えば、_source
から単一のフィールドを変更せずに取得したい場合、スクリプトは必要ありません。スクリプトなしでランタイムフィールドを作成することができます。例えば、day_of_week
のように:
Python
resp = client.indices.create(
index="my-index-000001",
mappings={
"runtime": {
"day_of_week": {
"type": "keyword"
}
}
},
)
print(resp)
Ruby
response = client.indices.create(
index: 'my-index-000001',
body: {
mappings: {
runtime: {
day_of_week: {
type: 'keyword'
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index-000001",
mappings: {
runtime: {
day_of_week: {
type: "keyword",
},
},
},
});
console.log(response);
コンソール
PUT my-index-000001/
{
"mappings": {
"runtime": {
"day_of_week": {
"type": "keyword"
}
}
}
}
スクリプトが提供されていない場合、Elasticsearch はクエリ時に _source
で同じ名前のフィールドを暗黙的に探し、存在する場合は値を返します。同じ名前のフィールドが存在しない場合、そのランタイムフィールドの値は応答に含まれません。
ほとんどの場合、可能な限り doc_values
を通じてフィールド値を取得してください。ランタイムフィールドを使用して doc_values
にアクセスする方が、_source
から値を取得するよりも速いです。これは、Lucene からデータが読み込まれる方法によるものです。
ただし、_source
からフィールドを取得する必要がある場合もあります。例えば、text
フィールドはデフォルトで doc_values
を利用できないため、_source
から値を取得する必要があります。他のケースでは、特定のフィールドで doc_values
を無効にすることを選択するかもしれません。
取得したい値のフィールドを params._source
でプレフィックスすることもできます(params._source.day_of_week
など)。簡潔さのために、スクリプトなしでマッピング定義にランタイムフィールドを定義することが推奨されます。
ランタイムフィールドのスクリプトエラーを無視する
スクリプトは、ドキュメント内の欠落または無効な値にアクセスしたり、無効な操作を実行したりする際に、ランタイムエラーをスローすることがあります。on_script_error
パラメータは、これが発生したときのエラー動作を制御するために使用できます。このパラメータを continue
に設定すると、このランタイムフィールドのすべてのエラーを静かに無視する効果があります。デフォルトの fail
値は、シャードの失敗を引き起こし、検索応答に報告されます。
ランタイムフィールドの更新と削除
ランタイムフィールドはいつでも更新または削除できます。既存のランタイムフィールドを置き換えるには、同じ名前の新しいランタイムフィールドをマッピングに追加します。マッピングからランタイムフィールドを削除するには、ランタイムフィールドの値を null
に設定します:
Python
resp = client.indices.put_mapping(
index="my-index-000001",
runtime={
"day_of_week": None
},
)
print(resp)
Ruby
response = client.indices.put_mapping(
index: 'my-index-000001',
body: {
runtime: {
day_of_week: nil
}
}
)
puts response
Js
const response = await client.indices.putMapping({
index: "my-index-000001",
runtime: {
day_of_week: null,
},
});
console.log(response);
コンソール
PUT my-index-000001/_mapping
{
"runtime": {
"day_of_week": null
}
}
下流への影響
依存クエリが実行中にランタイムフィールドを更新または削除すると、一貫性のない結果が返される可能性があります。各シャードは、マッピングの変更が有効になるタイミングに応じて、異なるバージョンのスクリプトにアクセスできる場合があります。
ランタイムフィールドに依存する既存のクエリやKibanaの視覚化は、フィールドを削除または更新すると失敗する可能性があります。例えば、ip
タイプのランタイムフィールドを使用する棒グラフの視覚化は、タイプが boolean
に変更された場合や、ランタイムフィールドが削除された場合に失敗します。