首页 > 解决方案 > Aggregate, Mongoose - 忽略重复的结果

问题描述

我有以下架构

var reviewSchema = new Schema({
    restaurantID: ObjectId,
    rating: {
     food: Number,
     service: Number,
     value: Number
    },
});

我想获得一系列平均食物、评级、服务评级,所以我这样做了

 Review.aggregate([
                    {
                        $match: {
                            restaurantID: mongoose.Types.ObjectId(reviewData.restaurantid)
                        }
                    },
                    {
                        $unwind: "$rating"
                    },
                    {
                        $group:{
                            _id: "$rating",
                            total_rating: { $avg: { $add: [ "$rating.food", "$rating.service", "$rating.value" ] } }
                        }
                    }
 ], function(review_error, reviews) {

但是,首先,它没有得到三个字段的平均值,它只得到字段的总和。没关系,我可以自己将其除以 3。最大的问题是它忽略了重复的结果。我试图将结果打印出来:

 [ { _id: { food: 4, service: 5, value: 4 }, total_rating: 13 },
  { _id: { food: 5, service: 5, value: 5 }, total_rating: 15 } ]

{ _id: { food: 5, service: 5, value: 5 }, total_rating: 15 }在收藏中有 6 条记录。我该如何解决这个问题?谢谢!

更新:示例

评论收藏

{ 
    "_id" : ObjectId("5af3d804d0d09e18b098208f"), 
    "rating" : {
        "food" : NumberInt(5), 
        "service" : NumberInt(5), 
        "value" : NumberInt(5)
    }, 
    "restaurantID" : ObjectId("5ac962bd437c1e30e89406a8"), 
}
{ 
    "_id" : ObjectId("5af3d817d0d09e18b0982090"), 
    "rating" : {
        "food" : NumberInt(5), 
        "service" : NumberInt(5), 
        "value" : NumberInt(5)
    }, 
    "restaurantID" : ObjectId("5ac962bd437c1e30e89406a8"), 
}
{ 
    "_id" : ObjectId("5af3d89161cc0a0e60f0925d"), 
    "rating" : {
        "food" : NumberInt(4), 
        "service" : NumberInt(5), 
        "value" : NumberInt(4)
    }, 
    "restaurantID" : ObjectId("5ac962bd437c1e30e89406a8"), 
}

预期结果

[ { _id: { food: 5, service: 5, value: 5 }, total_rating: 15 },
  { _id: { food: 4, service: 5, value: 4 }, total_rating: 13 },
  { _id: { food: 5, service: 5, value: 5 }, total_rating: 15 } ]

实际结果

   [ { _id: { food: 4, service: 5, value: 4 }, total_rating: 13 },
     { _id: { food: 5, service: 5, value: 5 }, total_rating: 15 } ]

标签: mongodbmongooseaggregation-framework

解决方案


不要$group。您只是试图“平均”文档中的值:

Review.aggregate([
  { "$addFields": {
     "average_rating": { "$avg": ["$rating.food", "$rating.service", "$rating.value" ]}
  }}
])

回报:

{
        "_id" : ObjectId("5af3d804d0d09e18b098208f"),
        "rating" : {
                "food" : 5,
                "service" : 5,
                "value" : 5
        },
        "restaurantID" : ObjectId("5ac962bd437c1e30e89406a8"),
        "average_rating" : 5
}
{
        "_id" : ObjectId("5af3d817d0d09e18b0982090"),
        "rating" : {
                "food" : 5,
                "service" : 5,
                "value" : 5
        },
        "restaurantID" : ObjectId("5ac962bd437c1e30e89406a8"),
        "average_rating" : 5
}
{
        "_id" : ObjectId("5af3d89161cc0a0e60f0925d"),
        "rating" : {
                "food" : 4,
                "service" : 5,
                "value" : 4
        },
        "restaurantID" : ObjectId("5ac962bd437c1e30e89406a8"),
        "average_rating" : 4.333333333333333
}

您真正想要的只是$avg三个值的结果,您可以使用$addFieldsor简单地做到这一点$project

管道阶段用于“$group分组”,因此为什么“相同的值”被“分组”在一起。

此外,如果您实际上想要“总计”,那么同样适用于$sum

Review.aggregate([
  { "$addFields": {
     "average_rating": { "$avg": ["$rating.food", "$rating.service", "$rating.value" ]},
     "total_rating": { "$sum": ["$rating.food", "$rating.service", "$rating.value" ]}
  }}
])

“每个文档”的类似结果:

{
        "_id" : ObjectId("5af3d804d0d09e18b098208f"),
        "rating" : {
                "food" : 5,
                "service" : 5,
                "value" : 5
        },
        "restaurantID" : ObjectId("5ac962bd437c1e30e89406a8"),
        "average_rating" : 5,
        "total_rating" : 15
}
{
        "_id" : ObjectId("5af3d817d0d09e18b0982090"),
        "rating" : {
                "food" : 5,
                "service" : 5,
                "value" : 5
        },
        "restaurantID" : ObjectId("5ac962bd437c1e30e89406a8"),
        "average_rating" : 5,
        "total_rating" : 15
}
{
        "_id" : ObjectId("5af3d89161cc0a0e60f0925d"),
        "rating" : {
                "food" : 4,
                "service" : 5,
                "value" : 4
        },
        "restaurantID" : ObjectId("5ac962bd437c1e30e89406a8"),
        "average_rating" : 4.333333333333333,
        "total_rating" : 13
}

推荐阅读