是的,有可能
$reduce
但有两个重要的警告:
-
里面
$let
当你定义
vars
第节您只能引用在外部作用域中定义的变量,但不能定义多个变量并在同一块中相互引用-这就是为什么这个解决方案中必须有大量嵌套的原因。
-
$reduce
暴露
$$value
表示聚合当前状态的变量。问题是你应该把这个变量当作
不变的
这意味着你可以引用它,但不能修改它
然后您可以尝试以下聚合:
db.col.aggregate([
{
$project: {
averages: {
$reduce: {
input: "$testScores",
initialValue: [],
in: {
$let: {
vars: {
index: { $indexOfArray: [ "$$value.id", "$$this.id" ] }
},
in: {
$let: {
vars: {
prev: {
$cond: [ { $ne: [ "$$index", -1 ] }, { $arrayElemAt: [ "$$value", "$$index" ] }, { id: "$$this.id", score: 0, count: 0 } ]
}
},
in: {
$let: {
vars: {
updated: {
id: "$$prev.id",
score: { $add: [ "$$prev.score", "$$this.score" ] },
count: { $add: [ "$$prev.count", 1 ] },
avg: {
$divide: [ { $add: [ "$$prev.score", "$$this.score" ] }, { $add: [ "$$prev.count", 1 ] } ]
}
}
},
in: {
$cond: {
if: { $eq: [ "$$index", -1 ] },
then: { $concatArrays: [ "$$value", [ "$$updated" ] ] },
else: { $concatArrays: [ { $slice: [ "$$value", "$$index"] }, [ "$$updated" ], { $slice: [ "$$value", { $add: [ "$$index", 1 ] }, { $size: "$$value" }] } ] }
}
}
}
}
}
}
}
}
}
}
}
}
])
其实每个
$let
在此定义算法步骤:
要返回值,我们应该考虑两种情况:
{
"averages" : [
{
"id" : "questionOne",
"score" : 14,
"count" : 4,
"avg" : 3.5
},
{
"id" : "questionFifty",
"score" : 14,
"count" : 4,
"avg" : 3.5
}
]
}