MongoDB 聚合管道中使用自定义聚合表达式运算符($accumulator)

自定义聚合表达式运算符主要通过自定义一些Javascript函数来完成更加复杂的聚合查询操作;本篇我们主要介绍$accumulator的使用:

一、准备工作

初始化课程成绩数据

db.subjectScores.insertMany([
    { "_id": 1, "name": "张三", "subject": "eng", "score": 80 },
    { "_id": 2, "name": "李四", "subject": "eng", "score": 60 },
    { "_id": 3, "name": "王五", "subject": "eng", "score": 90 },
    { "_id": 4, "name": "张三", "subject": "math", "score": 70 },
    { "_id": 5, "name": "李四", "subject": "math", "score": 90 },
    { "_id": 6, "name": "王五", "subject": "math", "score": 50 },
    { "_id": 7, "name": "张三", "subject": "physics", "score": 80 },
    { "_id": 8, "name": "李四", "subject": "physics", "score": 60 },
    { "_id": 9, "name": "王五", "subject": "physics", "score": 70 }
])

二、$accumulator

语法:

{
  $accumulator: {
    init: <code>,
    initArgs: <array expression>,        // Optional
    accumulate: <code>,
    accumulateArgs: <array expression>,
    merge: <code>,
    finalize: <code>,                    // Optional
    lang: <string>
  }
}

init:函数用于初始化state对象,从initArgs中接收参数

function (<initArg1>, <initArg2>, ...) {
  ...
  return <initialState>
}

initArgs:可选,初始化参数列表

[ <initArg1>, <initArg2>, ... ]

accumulate:函数用于累积文档,第一个参数是state对象,其他参数从accumulateArgs中接收;返回一个新的state对象

function(state, <accumArg1>, <accumArg2>, ...) {
  ...
  return <newState>
}

accumulateArgs:累积参数列表

[ <accumArg1>, <accumArg2>, ... ]

merge:函数用于合并两个state对象;返回一个新的state对象

function (<state1>, <state2>) {
  <logic to merge state1 and state2>
  return <newState>
}

finalize:函数用于返回聚合结果

function (state) {
  ...
  return <finalState>
}

lang: 使用的语言,目前仅支持js

$accumulator 在4.4及以后的版本中才能使用

三、例子:计算学生的总分数

聚合查询如下:

db.subjectScores.aggregate([
    {
        $group: {
            "_id": "$name",
            "score": {
                $accumulator: {
                    init: function() {
                        return {
                            sum: 0
                        }
                    },
                    accumulate: function(state, score) {
                        return {
                            sum: state.sum + score
                        }
                    },
                    accumulateArgs: [ "$score" ],
                    merge: function(state1, state2) {
                        return {
                            sum: state1.sum + state2.sum
                        }
                    },
                    finalize: function(state) {
                        return state.sum
                    },
                    lang: "js"
                }
            }
        }
    }
])

 我们对上面的聚合查询进行解释:

1、使用姓名对课程成绩文档进行分组

2、初始化state对象,对输入的文档中的score进行累加求和

3、合并state对象

4、返回state对象中的sum值作为总成绩

上面的聚合查询等效于:

db.subjectScores.aggregate([
    {
        $group: {
            "_id": "$name",
            "score": { $sum: "$score" }
        }
    }
])

聚合查询的结果如下:

{ "_id" : "王五", "score" : 210 }
{ "_id" : "李四", "score" : 210 }
{ "_id" : "张三", "score" : 230 }

猜你喜欢

转载自blog.csdn.net/m1729339749/article/details/130595027
今日推荐