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提供了$$ROOTvariables。 我的使用和输出可能不是你真正想要的:

 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'}} },