我的文档是这样的:
{
"_id" : "53ce85eda2579da8b40c1f0f",
"name" : "Autokino",
"tags" : [
"forMen"
],
"ratings" : [
{ "rating" : 5, "uuid" : "..."},
{ "rating" : 4, "uuid" : "..."},
{ "rating" : 4, "uuid" : "..."},
{ "rating" : 1, "uuid" : "..."},
]
}
现在我需要 ratings.rating 的平均值(这里应该是 3.5)。我的查询如下所示:
activities.aggregate([
{ $match: { _id: ObjectID(req.params.id) } },
{ $unwind: '$ratings' },
{ $group: {
_id: '$_id',
rating: { $avg: '$ratings.rating'},
}},
]);
它有效,但我得到的是:
{
"_id" : "53ce85eda2579da8b40c1f0f",
"rating" : 3.5
}
这就是我需要得到的:
{
"_id" : "53ce85eda2579da8b40c1f0f",
"name" : "Autokino",
"tags" : [
"forMen"
],
"rating" : 3.5
}
(没有评分数组但有评分平均值的原始文档)
我该如何解决这个问题?
最佳答案
流水线阶段,如 $group
和 $project
是“绝对”的,因为只发出声明的字段。你需要另一个接线员。 $first
会做:
activities.aggregate([
{ "$match": { "_id": ObjectID(req.params.id) } },
{ "$unwind": "$ratings" },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"tags": { "$first": "$tags" },
"rating": { "$avg": "$ratings.rating" },
}},
]);
自 $unwind
使数组内容中的许多文档反规范化,您可以使用 $first
此处仅取您未以其他方式聚合的附加字段的“第一次”出现。
如果您担心很多字段以这种方式声明,MongoDB 2.6 确实提供了 $$ROOT
多变的。它的用法和输出可能不是您真正想要的:
activities.aggregate([
{ "$match": { "_id": ObjectID(req.params.id) } },
{ "$project": {
"_id": "$$ROOT",
"ratings": 1
}},
{ "$unwind": "$ratings" },
{ "$group": {
"_id": "$_id",
"rating": { "$avg": "$ratings.rating" },
}},
]);
这给你类似的东西:
{
"_id" : {
"_id": "53ce85eda2579da8b40c1f0f",
"name" : "Autokino",
"tags" : [
"forMen"
],
"ratings" : [
{ "rating" : 5, "uuid" : "..."},
{ "rating" : 4, "uuid" : "..."},
{ "rating" : 4, "uuid" : "..."},
{ "rating" : 1, "uuid" : "..."},
]
},
"rating": 3.5
}
这里没问题,因为按 _id
分组与对整个文档进行分组相同。所以你总是可以添加最后一个 $project
回到相似的状态。但是这里没有通配符。
关于javascript - 嵌入数组的 MongoDB 平均值作为额外字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24906890/