スクリプトメトリック集約
スクリプトを使用してメトリック出力を提供するメトリック集約です。
スクリプトを使用すると、検索速度が遅くなる可能性があります。詳細は スクリプト、キャッシュ、および検索速度 を参照してください。
例:
Python
resp = client.search(
index="ledger",
size="0",
query={
"match_all": {}
},
aggs={
"profit": {
"scripted_metric": {
"init_script": "state.transactions = []",
"map_script": "state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)",
"combine_script": "double profit = 0; for (t in state.transactions) { profit += t } return profit",
"reduce_script": "double profit = 0; for (a in states) { profit += a } return profit"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'ledger',
size: 0,
body: {
query: {
match_all: {}
},
aggregations: {
profit: {
scripted_metric: {
init_script: 'state.transactions = []',
map_script: "state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)",
combine_script: 'double profit = 0; for (t in state.transactions) { profit += t } return profit',
reduce_script: 'double profit = 0; for (a in states) { profit += a } return profit'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "ledger",
size: 0,
query: {
match_all: {},
},
aggs: {
profit: {
scripted_metric: {
init_script: "state.transactions = []",
map_script:
"state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)",
combine_script:
"double profit = 0; for (t in state.transactions) { profit += t } return profit",
reduce_script:
"double profit = 0; for (a in states) { profit += a } return profit",
},
},
},
});
console.log(response);
コンソール
POST ledger/_search?size=0
{
"query": {
"match_all": {}
},
"aggs": {
"profit": {
"scripted_metric": {
"init_script": "state.transactions = []",
"map_script": "state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)",
"combine_script": "double profit = 0; for (t in state.transactions) { profit += t } return profit",
"reduce_script": "double profit = 0; for (a in states) { profit += a } return profit"
}
}
}
}
init_script はオプションのパラメータであり、他のすべてのスクリプトは必須です。 |
上記の集約は、スクリプト集約を使用して販売とコストトランザクションから総利益を計算する方法を示しています。
コンソール-結果
{
"took": 218,
...
"aggregations": {
"profit": {
"value": 240.0
}
}
}
上記の例は、次のように保存されたスクリプトを使用して指定することもできます:
Python
resp = client.search(
index="ledger",
size="0",
aggs={
"profit": {
"scripted_metric": {
"init_script": {
"id": "my_init_script"
},
"map_script": {
"id": "my_map_script"
},
"combine_script": {
"id": "my_combine_script"
},
"params": {
"field": "amount"
},
"reduce_script": {
"id": "my_reduce_script"
}
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'ledger',
size: 0,
body: {
aggregations: {
profit: {
scripted_metric: {
init_script: {
id: 'my_init_script'
},
map_script: {
id: 'my_map_script'
},
combine_script: {
id: 'my_combine_script'
},
params: {
field: 'amount'
},
reduce_script: {
id: 'my_reduce_script'
}
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "ledger",
size: 0,
aggs: {
profit: {
scripted_metric: {
init_script: {
id: "my_init_script",
},
map_script: {
id: "my_map_script",
},
combine_script: {
id: "my_combine_script",
},
params: {
field: "amount",
},
reduce_script: {
id: "my_reduce_script",
},
},
},
},
});
console.log(response);
コンソール
POST ledger/_search?size=0
{
"aggs": {
"profit": {
"scripted_metric": {
"init_script": {
"id": "my_init_script"
},
"map_script": {
"id": "my_map_script"
},
"combine_script": {
"id": "my_combine_script"
},
"params": {
"field": "amount"
},
"reduce_script": {
"id": "my_reduce_script"
}
}
}
}
}
init 、map 、および combine スクリプトのスクリプトパラメータは、グローバル params オブジェクト内で指定する必要があります。これにより、スクリプト間で共有できます。 |
スクリプトの指定に関する詳細は、スクリプトドキュメントを参照してください。
許可される戻り値の型
単一のスクリプト内で有効なスクリプトオブジェクトを使用できますが、スクリプトは state
オブジェクトに次の型のみを返すか保存する必要があります:
- プリミティブ型
- 文字列
- マップ(ここにリストされている型のキーと値のみを含む)
- 配列(ここにリストされている型の要素のみを含む)
スクリプトのスコープ
スクリプトメトリック集約は、実行の4つの段階でスクリプトを使用します:
- init_script
- ドキュメントの収集前に実行されます。集約が初期状態を設定できるようにします。
上記の例では、init_script
がstate
オブジェクト内に配列transactions
を作成します。 - map_script
- 収集された各ドキュメントごとに1回実行されます。これは必須のスクリプトです。
上記の例では、map_script
がタイプフィールドの値をチェックします。値が販売の場合、金額フィールドの値がトランザクション配列に追加されます。タイプフィールドの値が販売でない場合、金額フィールドの否定値がトランザクションに追加されます。 - combine_script
- ドキュメントの収集が完了した後、各シャードで1回実行されます。これは必須のスクリプトです。集約が各シャードから返された状態を統合できるようにします。
上記の例では、combine_script
がすべての保存されたトランザクションを反復処理し、profit
変数内の値を合計し、最終的にprofit
を返します。 - reduce_script
- すべてのシャードが結果を返した後、コーディネーティングノードで1回実行されます。これは必須のスクリプトです。スクリプトには、各シャードの combine_script の結果の配列である
states
変数へのアクセスが提供されます。
上記の例では、reduce_script
が各シャードから返されたprofit
を反復処理し、値を合計して最終的な合計利益を返します。これは集約の応答として返されます。
実例
次のドキュメントを2つのシャードを持つインデックスにインデックスする状況を想像してください:
Python
resp = client.bulk(
index="transactions",
refresh=True,
operations=[
{
"index": {
"_id": 1
}
},
{
"type": "sale",
"amount": 80
},
{
"index": {
"_id": 2
}
},
{
"type": "cost",
"amount": 10
},
{
"index": {
"_id": 3
}
},
{
"type": "cost",
"amount": 30
},
{
"index": {
"_id": 4
}
},
{
"type": "sale",
"amount": 130
}
],
)
print(resp)
Ruby
response = client.bulk(
index: 'transactions',
refresh: true,
body: [
{
index: {
_id: 1
}
},
{
type: 'sale',
amount: 80
},
{
index: {
_id: 2
}
},
{
type: 'cost',
amount: 10
},
{
index: {
_id: 3
}
},
{
type: 'cost',
amount: 30
},
{
index: {
_id: 4
}
},
{
type: 'sale',
amount: 130
}
]
)
puts response
Js
const response = await client.bulk({
index: "transactions",
refresh: "true",
operations: [
{
index: {
_id: 1,
},
},
{
type: "sale",
amount: 80,
},
{
index: {
_id: 2,
},
},
{
type: "cost",
amount: 10,
},
{
index: {
_id: 3,
},
},
{
type: "cost",
amount: 30,
},
{
index: {
_id: 4,
},
},
{
type: "sale",
amount: 130,
},
],
});
console.log(response);
コンソール
PUT /transactions/_bulk?refresh
{"index":{"_id":1}}
{"type": "sale","amount": 80}
{"index":{"_id":2}}
{"type": "cost","amount": 10}
{"index":{"_id":3}}
{"type": "cost","amount": 30}
{"index":{"_id":4}}
{"type": "sale","amount": 130}
ドキュメント1と3がシャードAに、ドキュメント2と4がシャードBに配置されるとしましょう。以下は、上記の例の各段階での集約結果の内訳です。
init_scriptの前
state
は新しい空のオブジェクトとして初期化されます。
Js
"state" : {}
init_scriptの後
これは、ドキュメントの収集が行われる前に各シャードで1回実行され、各シャードにコピーが作成されます:
- シャードA
Js
"state" : {
"transactions" : []
}
- シャードB
Js
"state" : {
"transactions" : []
}
map_scriptの後
各シャードはドキュメントを収集し、収集された各ドキュメントに対して map_script を実行します:
- シャードA
Js
"state" : {
"transactions" : [ 80, -30 ]
}
- シャードB
Js
"state" : {
"transactions" : [ -10, 130 ]
}
combine_scriptの後
combine_script は、ドキュメントの収集が完了した後、各シャードで実行され、すべてのトランザクションを単一の利益数値に減少させます(トランザクション配列内の値を合計することによって)これがコーディネーティングノードに渡されます:
- シャードA
- 50
- シャードB
- 120
reduce_scriptの後
reduce_script は、各シャードの combine スクリプトの結果を含む states
配列を受け取ります:
Js
"states" : [
50,
120
]
シャードの応答を最終的な全体の利益数値に減少させ(値を合計することによって)、これを集約の結果として返します。
Js
{
...
"aggregations": {
"profit": {
"value": 170
}
}
}
その他のパラメータ
params | オプション。init_script 、map_script 、および combine_script に変数として渡される内容を持つオブジェクトです。これは、ユーザーが集約の動作を制御し、スクリプト間で状態を保存できるようにするために役立ちます。これが指定されていない場合、デフォルトは次の提供と同等です:#### Js {$pre20} |
空のバケット
スクリプトメトリック集約の親バケットがドキュメントを収集しない場合、null
値を持つ空の集約応答がシャードから返されます。この場合、reduce_script
の states
変数は、そのシャードからの応答として null
を含みます。したがって、reduce_script
はシャードからの null
応答を期待し、対処する必要があります。