MongoDB平均embedded式数组作为额外的领域
我的文件看起来像这样:
{ "_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 }
(没有评级arrays但评级平均的原始文件)
我怎么解决这个问题?
像$group
和$project
这样的stream水线阶段是“绝对的”,因为只有声明的字段被发射。 这里需要另一个操作员。 $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
variables。 我的使用和输出可能不是你真正想要的:
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
来返回到类似的状态。 但是这里没有通配符。
我刚刚经历了这整首歌并跳舞,最后不得不重新添加我的所有场地。 不理想!
所以我只是发现这一点 – 更容易:我有一个评论arrays字段,其评级属性为1 – 5
{ $addFields: { avg: { $avg: '$reviews.rating'}} },