自定义聚合表达式运算符主要通过自定义一些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 }