Bạn không thể sử dụng aggregation
để cập nhật tài liệu, nhưng bạn chắc chắn có thể sử dụng nó để lấy dữ liệu bạn muốn sử dụng cho bản cập nhật. Trước hết, tôi nhận thấy rằng có một số {}
thiếu grade
của bạn đối tượng bên trong grades
mảng. Bạn có thể muốn kiểm tra lại xem cấu trúc tài liệu của mình có đúng như đã đăng hay không. Thứ hai, có một số vấn đề với truy vấn tổng hợp của bạn.
-
$avg
toán tử hoạt động bên trong$group
mệnh đề, không phải là$project
. - Khi bạn sử dụng
$avg
, bạn không cần sử dụng$sum
. - Bạn muốn trung bình
trucks.grades.grade.grade_number
, thực sự giữ giá trị số của lớp. Tức là bạn đang thiếugrades
giữagrade
vàgrade_number
.
Nếu bạn giải quyết những vấn đề đó, bạn sẽ nhận được một truy vấn tương tự như sau:
db.col.aggregate([
{ "$unwind": "$trucks" },
{ "$unwind": "$trucks.grades" },
{ "$group":
{
"_id": "$trucks.truck_id",
"average_grade": { "$avg": "$trucks.grades.grade_number" }
}
}
]);
Đối với tài liệu mẫu của bạn, trả về:
{ "_id" : "TEB5572", "average_grade" : 4 }
{ "_id" : "TEB7622", "average_grade" : 4 }
Bây giờ, bạn có thể sử dụng thông tin này để cập nhật average_grade
đồng ruộng. Nếu bạn đang sử dụng MongoDB phiên bản 2.6 trở lên, aggregation
phương thức sẽ trả về một con trỏ. Bạn có thể lặp lại qua con trỏ đó và cập nhật tài liệu cho phù hợp.
Trong ví dụ này, tôi tìm kiếm các tài liệu có truck_id
cụ thể bên trong trucks
của họ mảng và tiến hành cập nhật average_grade
với một tính toán bởi truy vấn tổng hợp. Bạn có thể sửa đổi nó cho phù hợp với nhu cầu của bạn. Được kết hợp với truy vấn tổng hợp, mã trông như thế này.
// 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});
}