MongoDB聚合操作符:$accumulator

$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操作符处理文档的过程和步骤:

  1. 操作符从初始状态开始,由init函数定义。
  2. 操作符基于accumulate指定的函数更新每个文档的状态。
  3. 当操作符需要合并多个中间状态时,会执行merge函数。
  4. 如果定义了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-91MozJS-60中存在的一些不推荐使用的非标准数组和字符串函数在MozJS-91中被删除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

原子星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值