【问题标题】:Aggregating an array of object field using mongoose - Rating calculation使用 mongoose 聚合对象字段数组 - 评分计算
【发布时间】:2021-06-06 01:13:27
【问题描述】:

我有一个看起来像这样的产品模型:

{
   "name":"Natural Product",
   "ratings":[
      {
         "user":"5fdce4bd75dbe4864fcd5001",
         "rating":5
      },
      {
         "user":"5fdce4bd75dbe4864fcd5002",
         "rating":4
      }
   ]
}

我尝试使用以下查询获得产品型号的平均评分

db.products.aggregate([
  {$match: {
    _id: {$exists: true}
  }},
  {$group: {_id: "$_id", rating: { $avg: "$ratings.rating"}}}
])

但是我得到的响应是这样的:

{ "_id" : ObjectId("60baf573246539ec265efd41"), "rating" : null }

在试图找出问题所在时,我插入了一个新的虚拟数据,只是结构略有不同:

{
   "name":"Natural Product",
   "ratings":{
     "user": "5fdce4bd75dbe4864fcd5001",
     "rating": 5
   }
}

它给了我这个合理的回应:

{ "_id" : ObjectId("60bafb72246539ec265efd42"), "rating" : 5 }

请问我应该如何查询数据库以获得数组格式的评分平均值?

【问题讨论】:

  • 在 $match 阶段之后添加新阶段,{ $unwind: "$ratings" },它将解构评级数组。

标签: node.js mongodb aggregation-framework


【解决方案1】:

如果你有比 mongodb server v3.2 更新的版本,$avg 可以在 $project 阶段使用

db.products.aggregate(
[
    {
        $project: {
            _id: 1,
            rating: { $avg: "$ratings.rating" }
        }
    }
])

https://mongoplayground.net/p/uehHGxI3ybU

【讨论】:

    【解决方案2】:

    在对象数组上执行此操作会令人困惑。 Mongo 不知道要访问数组中的哪个元素。所以我们需要unwind它来解构它。
    这将起作用

    db.collection.aggregate([
      {
        $match: {
          _id: {
            $exists: true
          }
        }
      },
      {
        $unwind: "$ratings"
      },
      {
        $group: {
          _id: "$_id",
          rating: {
            $avg: "$ratings.rating"
          }
        }
      }
    ])
    

    Working example for mongo playground

    【讨论】:

      猜你喜欢
      • 2021-08-27
      • 1970-01-01
      • 1970-01-01
      • 2020-03-19
      • 2023-03-14
      • 2014-02-27
      • 2021-09-17
      • 2018-09-01
      • 2018-09-17
      相关资源
      最近更新 更多