$accumulator可以定义自定义累加器操作符。累加器是一种操作符,可在文档通过管道时保持其状态(如:总数、最大值、最小值和相关数据)。$accumulator操作符支持执行自定义的JavaScript函数,可以实现MongoDB查询语言不支持的行为。
$accumulator支持下列阶段:
$bucket$bucketAuto$group
**注意:**在聚合操作符内部执行JavaScript可能会降低性能,只有在MongoDB提供的管道操作符无法满足需求时才考虑使用$accumulator。
语法
{
$accumulator: {
init: <code>,
initArgs: <array expression>, // 可选
accumulate: <code>,
accumulateArgs: <array expression>,
merge: <code>,
finalize: <code>, // 可选
lang: <string>
}
}
字段说明:
-
init
字符串或代码,用于初始化状态的函数。init函数从initArgs数组接受参数,可以使用BSON类型代码或字符串来定义函数,init函数形式如下:function (<initArg1>, <initArg2>, ...) { ... return <initialState> }**注意:**溢出到磁盘或在分片集群上运行查询会导致累加器以多个子累加器合并的形式计算,每个函数都以调用
init()开始。要确保init()、accumulative()和merge()函数与此执行模式兼容。 -
initArgs
数组,可选,传递给init函数的参数。initArgs为下面的形式:[ <initArg1>, <initArg2>, ... ]**注意:**应用于
$bucketAuto阶段时,initArgs不能应用分组键(也就是说不能使用$<fieldName>语法),换而言之,在$bucketAuto阶段,只能给initArgs指定常量。 -
accumulate
字符串或代码,用于文档累加的函数,accumulate函数从accumulateArgs数组表达式接受当前状态和参数,accumulate函数的返回值变为新状态,函数定义可以为BSON类型的代码或字符串。accumulate函数的形式如下:function(state, <accumArg1>, <accumArg2>, ...) { ... return <newState> } -
accumulateArgs
传递给accumulate函数的参数,可以使用accumulateArgs来制定传递给accmulate函数的字段值。accumulateArgs的形式如下;[ <accumArg1>, <accumArg2>, ... ] -
merge
字符串或代码,用于合并两个内部状态的函数,merge必须是字符串或BSON代码类型,merge返回两个状态合并后的结果,mere函数的形式如下:function (<state1>, <state2>) { <logic to merge state1 and state2> return <newState> } -
finalize
字符串或代码,可选,用于更新累加结果的函数。finalize函数的形式如下:function (state) { ... return <finalState> } -
lang
字符串类型,accumulator代码使用的语言。目前仅支持js。
使用
下面是$accumulator操作符处理文档的过程和步骤:
- 操作符从初始状态开始,由
init函数定义。 - 操作符基于
accumulate指定的函数更新每个文档的状态。 - 当操作符需要合并多个中间状态时,会执行
merge函数。 - 如果定义了
finalize函数,一旦所有文档被处理完并且状态因此更新,最终确定将状态到最终输出。
使用$merge合并两个状态
作为其内部运作的一部分,累加器操作符可能需要合并两个独立的中间状态。合并函数指定操作符应如何合并两个状态。
例如,下面的情况下,$accumulator可能需要合并两个状态:
$accumulator运行在分片集群上,操作符需要合并每个分片的结果,以得到的最终结果。- 单个
$accumulator操作超出了它指定的内存限制,如果指定了alloDiskUse选项,操作符将正在进行的操作放在磁盘上并在内存中完成操作。一旦操作完成,磁盘上、内存中的的结果将由merge函数进行合并。
**注意:**合并函数总是一次合并两个状态。当有两个以上状态需要合并时,则会先合并两个状态为一个状态,然后重复这一过程,直到所有的状态都被合并。也就是说每次合并只能合并两个状态。
内嵌javascript
要使用$accumulator,必须启用服务端脚本选项。如果不使用$accumulator(或$function、$where、或mapRecuce),可以禁用服务端脚本:
- 对于
mongod实例,可以参考security.javascriptEnabled选项配置或--noscripting命令行选项。 - 对于
mongos实例,可以参考security.javascriptEnabled选项配置或--noscripting命令行选项(从MongoDB4.4开始)。
对于更早的版本,MongoDB不允许在mongos实例上执行JavaScript。
不支持的数组和字符串函数
MongoDB6.0升级了用于服务端JavaScript的内部JavaScript引擎,包括$accumulator、$function和$where表达式,从MozJS-60升级到了MozJS-91,MozJS-60中存在的一些不推荐使用的非标准数组和字符串函数在MozJS-91中被删除。

最低0.47元/天 解锁文章
6009

被折叠的 条评论
为什么被折叠?



