ドキュメントフィールドと特別な変数へのアクセス
スクリプトが使用される場所に応じて、特定の特別な変数やドキュメントフィールドにアクセスできます。
ドキュメントフィールドと特別な変数へのアクセス
スクリプトが使用される場所に応じて、特定の特別な変数やドキュメントフィールドにアクセスできます。
検索および集約スクリプト
検索ヒットごとに一度実行される スクリプトフィールド を除いて、検索および集約で使用されるスクリプトは、クエリまたは集約に一致する可能性のある各ドキュメントごとに一度実行されます。ドキュメントの数によっては、これは数百万または数十億回の実行を意味する可能性があります: これらのスクリプトは高速である必要があります!
フィールド値は、doc-values、_source
フィールド、または ストレージフィールド を使用してスクリプトからアクセスできます。これらは以下で説明します。
スクリプト内でのドキュメントのスコアへのアクセス
function_score
クエリ、スクリプトベースのソート、または 集約 で使用されるスクリプトは、ドキュメントの現在の関連性スコアを表す _score
変数にアクセスできます。
以下は、function_score
クエリ でスクリプトを使用して各ドキュメントの関連性 _score
を変更する例です:
Python
resp = client.index(
index="my-index-000001",
id="1",
refresh=True,
document={
"text": "quick brown fox",
"popularity": 1
},
)
print(resp)
resp1 = client.index(
index="my-index-000001",
id="2",
refresh=True,
document={
"text": "quick fox",
"popularity": 5
},
)
print(resp1)
resp2 = client.search(
index="my-index-000001",
query={
"function_score": {
"query": {
"match": {
"text": "quick brown fox"
}
},
"script_score": {
"script": {
"lang": "expression",
"source": "_score * doc['popularity']"
}
}
}
},
)
print(resp2)
Ruby
response = client.index(
index: 'my-index-000001',
id: 1,
refresh: true,
body: {
text: 'quick brown fox',
popularity: 1
}
)
puts response
response = client.index(
index: 'my-index-000001',
id: 2,
refresh: true,
body: {
text: 'quick fox',
popularity: 5
}
)
puts response
response = client.search(
index: 'my-index-000001',
body: {
query: {
function_score: {
query: {
match: {
text: 'quick brown fox'
}
},
script_score: {
script: {
lang: 'expression',
source: "_score * doc['popularity']"
}
}
}
}
}
)
puts response
Js
const response = await client.index({
index: "my-index-000001",
id: 1,
refresh: "true",
document: {
text: "quick brown fox",
popularity: 1,
},
});
console.log(response);
const response1 = await client.index({
index: "my-index-000001",
id: 2,
refresh: "true",
document: {
text: "quick fox",
popularity: 5,
},
});
console.log(response1);
const response2 = await client.search({
index: "my-index-000001",
query: {
function_score: {
query: {
match: {
text: "quick brown fox",
},
},
script_score: {
script: {
lang: "expression",
source: "_score * doc['popularity']",
},
},
},
},
});
console.log(response2);
コンソール
PUT my-index-000001/_doc/1?refresh
{
"text": "quick brown fox",
"popularity": 1
}
PUT my-index-000001/_doc/2?refresh
{
"text": "quick fox",
"popularity": 5
}
GET my-index-000001/_search
{
"query": {
"function_score": {
"query": {
"match": {
"text": "quick brown fox"
}
},
"script_score": {
"script": {
"lang": "expression",
"source": "_score * doc['popularity']"
}
}
}
}
}
ドキュメント値
スクリプトからフィールド値にアクセスする最も高速で効率的な方法は、doc['field_name']
構文を使用することです。これは、doc values からフィールド値を取得します。ドキュメント値は、すべてのフィールドに対してデフォルトで有効になっている列指向のフィールド値ストアで、分析された text
フィールド を除きます。
Python
resp = client.index(
index="my-index-000001",
id="1",
refresh=True,
document={
"cost_price": 100
},
)
print(resp)
resp1 = client.search(
index="my-index-000001",
script_fields={
"sales_price": {
"script": {
"lang": "expression",
"source": "doc['cost_price'] * markup",
"params": {
"markup": 0.2
}
}
}
},
)
print(resp1)
Ruby
response = client.index(
index: 'my-index-000001',
id: 1,
refresh: true,
body: {
cost_price: 100
}
)
puts response
response = client.search(
index: 'my-index-000001',
body: {
script_fields: {
sales_price: {
script: {
lang: 'expression',
source: "doc['cost_price'] * markup",
params: {
markup: 0.2
}
}
}
}
}
)
puts response
Js
const response = await client.index({
index: "my-index-000001",
id: 1,
refresh: "true",
document: {
cost_price: 100,
},
});
console.log(response);
const response1 = await client.search({
index: "my-index-000001",
script_fields: {
sales_price: {
script: {
lang: "expression",
source: "doc['cost_price'] * markup",
params: {
markup: 0.2,
},
},
},
},
});
console.log(response1);
コンソール
PUT my-index-000001/_doc/1?refresh
{
"cost_price": 100
}
GET my-index-000001/_search
{
"script_fields": {
"sales_price": {
"script": {
"lang": "expression",
"source": "doc['cost_price'] * markup",
"params": {
"markup": 0.2
}
}
}
}
}
ドキュメント値は、数値、日付、地理的ポイント、用語などの「単純な」フィールド値や、フィールドが多値の場合はこれらの値の配列のみを返すことができます。JSONオブジェクトを返すことはできません。
欠落しているフィールド
doc['field']
は、field
がマッピングから欠落している場合にエラーをスローします。painless
では、doc.containsKey('field')
を使用して doc
マップへのアクセスを保護するために最初にチェックを行うことができます。残念ながら、expression
スクリプト内でマッピングにフィールドの存在を確認する方法はありません。
ドキュメント値とテキストフィールド
doc['field']
構文は、text
フィールド に対しても使用できますが、fielddata
が有効になっている場合に限ります。ただし、注意: text
フィールドでフィールドデータを有効にすると、すべての用語がJVMヒープにロードされる必要があり、メモリとCPUの両方の観点から非常に高価になる可能性があります。スクリプトから text
フィールドにアクセスすることはほとんど意味がありません。
ドキュメント _source
ドキュメント _source
は、_source.field_name
構文を使用してアクセスできます。_source
はマップのマップとしてロードされるため、オブジェクトフィールド内のプロパティには、例えば _source.name.first
のようにアクセスできます。
ドキュメント値を _source より優先する
_source
フィールドへのアクセスは、ドキュメント値を使用するよりもはるかに遅くなります。_source フィールドは、結果ごとに複数のフィールドを返すように最適化されているのに対し、ドキュメント値は多くのドキュメント内の特定のフィールドの値にアクセスするように最適化されています。
検索結果の上位10件から スクリプトフィールド を生成する際には _source
を使用するのが理にかなっていますが、他の検索および集約のユースケースでは、常にドキュメント値を使用することを優先してください。
例えば:
Python
resp = client.indices.create(
index="my-index-000001",
mappings={
"properties": {
"first_name": {
"type": "text"
},
"last_name": {
"type": "text"
}
}
},
)
print(resp)
resp1 = client.index(
index="my-index-000001",
id="1",
refresh=True,
document={
"first_name": "Barry",
"last_name": "White"
},
)
print(resp1)
resp2 = client.search(
index="my-index-000001",
script_fields={
"full_name": {
"script": {
"lang": "painless",
"source": "params._source.first_name + ' ' + params._source.last_name"
}
}
},
)
print(resp2)
Ruby
response = client.indices.create(
index: 'my-index-000001',
body: {
mappings: {
properties: {
first_name: {
type: 'text'
},
last_name: {
type: 'text'
}
}
}
}
)
puts response
response = client.index(
index: 'my-index-000001',
id: 1,
refresh: true,
body: {
first_name: 'Barry',
last_name: 'White'
}
)
puts response
response = client.search(
index: 'my-index-000001',
body: {
script_fields: {
full_name: {
script: {
lang: 'painless',
source: "params._source.first_name + ' ' + params._source.last_name"
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index-000001",
mappings: {
properties: {
first_name: {
type: "text",
},
last_name: {
type: "text",
},
},
},
});
console.log(response);
const response1 = await client.index({
index: "my-index-000001",
id: 1,
refresh: "true",
document: {
first_name: "Barry",
last_name: "White",
},
});
console.log(response1);
const response2 = await client.search({
index: "my-index-000001",
script_fields: {
full_name: {
script: {
lang: "painless",
source: "params._source.first_name + ' ' + params._source.last_name",
},
},
},
});
console.log(response2);
コンソール
PUT my-index-000001
{
"mappings": {
"properties": {
"first_name": {
"type": "text"
},
"last_name": {
"type": "text"
}
}
}
}
PUT my-index-000001/_doc/1?refresh
{
"first_name": "Barry",
"last_name": "White"
}
GET my-index-000001/_search
{
"script_fields": {
"full_name": {
"script": {
"lang": "painless",
"source": "params._source.first_name + ' ' + params._source.last_name"
}
}
}
}
ストレージフィールド
ストレージフィールド—マッピングで明示的に "store": true
としてマークされたフィールド—は、_fields['field_name'].value
または _fields['field_name']
構文を使用してアクセスできます:
Python
resp = client.indices.create(
index="my-index-000001",
mappings={
"properties": {
"full_name": {
"type": "text",
"store": True
},
"title": {
"type": "text",
"store": True
}
}
},
)
print(resp)
resp1 = client.index(
index="my-index-000001",
id="1",
refresh=True,
document={
"full_name": "Alice Ball",
"title": "Professor"
},
)
print(resp1)
resp2 = client.search(
index="my-index-000001",
script_fields={
"name_with_title": {
"script": {
"lang": "painless",
"source": "params._fields['title'].value + ' ' + params._fields['full_name'].value"
}
}
},
)
print(resp2)
Ruby
response = client.indices.create(
index: 'my-index-000001',
body: {
mappings: {
properties: {
full_name: {
type: 'text',
store: true
},
title: {
type: 'text',
store: true
}
}
}
}
)
puts response
response = client.index(
index: 'my-index-000001',
id: 1,
refresh: true,
body: {
full_name: 'Alice Ball',
title: 'Professor'
}
)
puts response
response = client.search(
index: 'my-index-000001',
body: {
script_fields: {
name_with_title: {
script: {
lang: 'painless',
source: "params._fields['title'].value + ' ' + params._fields['full_name'].value"
}
}
}
}
)
puts response
Js
const response = await client.indices.create({
index: "my-index-000001",
mappings: {
properties: {
full_name: {
type: "text",
store: true,
},
title: {
type: "text",
store: true,
},
},
},
});
console.log(response);
const response1 = await client.index({
index: "my-index-000001",
id: 1,
refresh: "true",
document: {
full_name: "Alice Ball",
title: "Professor",
},
});
console.log(response1);
const response2 = await client.search({
index: "my-index-000001",
script_fields: {
name_with_title: {
script: {
lang: "painless",
source:
"params._fields['title'].value + ' ' + params._fields['full_name'].value",
},
},
},
});
console.log(response2);
コンソール
PUT my-index-000001
{
"mappings": {
"properties": {
"full_name": {
"type": "text",
"store": true
},
"title": {
"type": "text",
"store": true
}
}
}
}
PUT my-index-000001/_doc/1?refresh
{
"full_name": "Alice Ball",
"title": "Professor"
}
GET my-index-000001/_search
{
"script_fields": {
"name_with_title": {
"script": {
"lang": "painless",
"source": "params._fields['title'].value + ' ' + params._fields['full_name'].value"
}
}
}
}
ストレージと _source
_source
フィールドは特別なストレージフィールドに過ぎないため、パフォーマンスは他のストレージフィールドと同様です。_source
は、インデックスされた元のドキュメント本文へのアクセスを提供します(null
値を空のフィールド、単一値の配列、プレーンスカラーなどから区別する能力を含む)。
_source
フィールドの代わりにストレージフィールドを使用することが本当に意味を持つのは、_source
が非常に大きく、全体の _source
にアクセスするよりもいくつかの小さなストレージフィールドにアクセスする方がコストが低い場合だけです。