5.1.11. Scripted Metric Aggregation

脚本式指标聚合

使用脚本执行以提供度量标准输出的度量标准聚合。

例子:

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"
            }
        }
    }
}
  1. init_script 是可选参数,所有其他脚本都是必需的。

以上聚合演示了如何使用脚本汇总来计算销售和成本交易的总利润。

以上聚合的响应:

{
    "took": 218,
    ...
    "aggregations": {
        "profit": {
            "value": 240.0
        }
   }
}

也可以使用存储的脚本指定上述示例,如下所示:

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"
                }
            }
        }
    }
}
  1. 必须在全局 params 对象中指定initmap和合并脚本的脚本参数,以便可以在脚本之间共享。

有关指定脚本的更多详细信息,请参见脚本文档.

允许的返回类型

虽然任何有效的脚本对象都可以在一个脚本中使用,但脚本必须返回或存储在state对象中只有以下类型:

  • 基本类型
  • 字符串
  • 映射 (只包含此处列出的类型的键和值)
  • 数组 (仅包含此处列出的类型的元素)

脚本范围

脚本度量聚合在执行的4个阶段使用脚本:

  • init_script
    在收集任何文件之前执行。允许聚合设置任何初始状态。
    在上面的示例中,init_scriptstate对象中创建一个数组transactions

  • map_script

每个收集的文档执行一次。这是必需的脚本。如果未指定combine_script,则需要将结果状态存储在state对象中。

在上面的示例中,map_script检查类型字段的值。如果值为 sale,则金额字段的值将添加到交易数组中。如果类型字段的值不是 sale,则金额字段的取反值将添加到交易中。

  • combine_script

    文档收集完成后,对每个分片执行一次。这是必需的脚本。允许聚合合并从每个分片返回的状态。

    在上面的示例中,combine_script遍历所有存储的交易,对profit变量中的值求和,最后返回profit

  • reduce_script

    所有分片均返回其结果后,在协调节点上执行一次。这是必需的脚本。该脚本可以访问变量states,该变量是每个分片上 combine_script 结果的数组。

    在上面的示例中,reduce_script通过每个分片返回的profit进行迭代,然后在返回最终的合并利润之前返回每个合并的值,该合并后的利润将被返回。

工作示例

想象一下您将以下文档编入带有2个分片的索引的情况

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 被初始化为新的空对象。

"state"  :  {}

初始化 init_script 后

在执行任何文档收集之前,此操作在每个分片上运行一次,因此我们在每个分片上都有一个副本:
分片 A

"state"  :  {  "transactions"  :  []  }

分片 B

"state"  :  {  "transactions"  :  []  }

map_script 后

每个分片都会收集其文档,并在收集到的每个文档上运行 map_script:
分片 A

"state"  :  {  "transactions"  :  [  80,  -30  ]  }

分片 B

"state"  :  {  "transactions"  :  [  -10,  130  ]  }

combine_script 之后

在文档收集完成之后,对每个分片执行 combine_script,并将每个分片的所有交易降低为单个利润数字(通过对交易数组中的值求和),然后将其传递回协调节点:

分片 A

50

分片 B

120

reduce_script 之后

reduce_script 接受另一个 states数组,其中包含每个分片的合并脚本的结果:

"states" : [
    50,
    120
]

它将分片的响应降低到最终的总利润数字(通过对值求和),并将其作为聚合结果返回以产生响应:

{
    ...

    "aggregations": {
        "profit": {
            "value": 170
        }
   }
}

其他参数

  • params
    可选的。一个对象,其内容将作为变量传递到 init_scriptmap_scriptcombine_script。这对于允许用户控制聚合的行为以及在脚本之间存储状态很有用。如果未指定,则默认等效于提供:
    "params"  :  {} 

空桶

如果脚本化指标聚合的父桶未收集任何文档,则分片将返回空聚合响应,并带有null值。在这种情况下,reduce_scriptstatus变量将包含null作为该分片的响应。因此,reduce_script应该期望并处理分片的null响应。

Empty Buckets

If a parent bucket of the scripted metric aggregation does not collect any documents an empty aggregation response will be returned from the shard with a null value. In this case the reduce_script's states variable will contain null as a response from that shard. reduce_script's should therefore expect and deal with null responses from shards.

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
CrazyZard
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~