MongoDB:使用2个嵌套数组更新文档中的平均值

时间:2015-02-27 01:32:24

标签: arrays mongodb mongodb-query

我有以下MongoDB文档:

{
    _id: ObjectId(),
    company_name: "Name",
    registered: 2/21/2015 2:00,
    trucks: [
        {
            truck_id: "TEB7622",
            weight: 88.33,
            capacity: 273.333,
            length: 378.333,
            width: 377.383,
            average_grade: 2.5,
            grades: [
                {
                    grade_number: 4,
                    timestamp: 2/21/2015 2:00
                }
            ]
        },
        {
            truck_id: "TEB5572",
            weight: 854.33,
            capacity: 2735.333,
            length: 378.333,
            width: 37.383,
            average_grade: 3.8,
            grades: [
                {
                    grade_number: 4,
                    timestamp: 2/21/2015 2:00
                }
            ]
        }
    ]

}

我希望通过添加所有average_grade来更新每辆卡车的grade_numbers。我遇到的问题是我尝试添加的grade_numbers是在数组中的数组中。我尝试使用$unwind展开卡车和等级阵列。

这是我尝试使用的查询:

db.col.aggregate([ 
   {$unwind: "$trucks"}, 
   {$unwind: "$trucks.grades"}, 
   { $project: { 
      "_id": "$trucks.truck_id", 
      "trucks.average_grade": { $avg: { $sum: "trucks.grades.grade_number"} } 
      } 
   }])

我是否需要在查询中添加更多内容?我想更新所有trucks.average_grades,因为我想要更新的文档中有很多这些。{/ p>

1 个答案:

答案 0 :(得分:6)

您无法使用aggregation更新文档,但您绝对可以使用它来获取要用于更新的数据。首先,我注意到{}数组中的grade对象周围缺少grades$avg。您可能需要仔细检查文档结构是否已发布。其次,您的聚合查询存在一些问题。

  1. $group运算符适用于$project子句,而不是$avg
  2. 使用$sum时,您无需使用trucks.grades.grade.grade_number
  3. 您希望平均grade,它实际上包含成绩的数值。也就是说,您在gradesgrade_number之间缺少db.col.aggregate([ { "$unwind": "$trucks" }, { "$unwind": "$trucks.grades" }, { "$group": { "_id": "$trucks.truck_id", "average_grade": { "$avg": "$trucks.grades.grade_number" } } } ]);
  4. 如果您解决了这些问题,则会收到类似以下内容的查询:

    { "_id" : "TEB5572", "average_grade" : 4 }
    { "_id" : "TEB7622", "average_grade" : 4 }
    

    对于您的示例文档,它返回:

    average_grade

    现在,您可以使用此信息更新aggregate字段。如果您使用的是MongoDB 2.6或更高版本,truck_id方法将返回游标。您可以遍历该游标并相应地更新文档。

    在此示例中,我搜索其trucks数组中具有特定average_grade的文档,然后使用聚合查询计算的文档继续更新// Get average grade for each truck and assign results to cursor. var cur = db.col.aggregate([ { "$unwind": "$trucks" }, { "$unwind": "$trucks.grades" }, { "$group": { "_id": "$trucks.truck_id", "average_grade": { "$avg": "$trucks.grades.grade_number" } } } ]); // Iterate through results and update average grade for each truck. while (cur.hasNext()) { var doc = cur.next(); db.col.update({ "trucks.truck_id": doc._id }, { "$set": { "trucks.$.average_grade": doc.average_grade }}, { "multi": true}); } 。您可以根据自己的需要进行修改。结合聚合查询,代码如下所示。

    {{1}}