Nie możesz użyć aggregation
do aktualizacji dokumentu, ale zdecydowanie możesz go użyć, aby uzyskać dane, których chcesz użyć do aktualizacji. Przede wszystkim zauważyłem, że istnieje kilka {}
brakuje w okolicy grade
obiekt wewnątrz grades
szyk. Możesz dokładnie sprawdzić, czy struktura Twojego dokumentu jest taka, jak została opublikowana. Po drugie, jest kilka problemów z zapytaniem agregującym.
$avg
operator działa wewnątrz$group
klauzula, a nie$project
.- Gdy używasz
$avg
, nie musisz używać$sum
. - Chcesz uśrednić
trucks.grades.grade.grade_number
, który faktycznie zawiera wartość liczbową oceny. Oznacza to, że brakuje Cigrade
międzygrades
igrade_number
.
Jeśli rozwiążesz te problemy, otrzymasz zapytanie podobne do następującego:
db.col.aggregate([
{ "$unwind": "$trucks" },
{ "$unwind": "$trucks.grades" },
{ "$group":
{
"_id": "$trucks.truck_id",
"average_grade": { "$avg": "$trucks.grades.grade_number" }
}
}
]);
W przypadku przykładowego dokumentu, który zwraca:
{ "_id" : "TEB5572", "average_grade" : 4 }
{ "_id" : "TEB7622", "average_grade" : 4 }
Teraz możesz użyć tych informacji, aby zaktualizować average_grade
pole. Jeśli używasz MongoDB w wersji 2.6 lub nowszej, aggregate
metoda zwróci kursor. Możesz przejść przez ten kursor i odpowiednio zaktualizować dokumenty.
W tym przykładzie szukam dokumentów, które mają określony truck_id
wewnątrz ich trucks
i przejdź do aktualizacji average_grade
z wartością obliczoną przez zapytanie agregujące. Możesz go dostosować do swoich potrzeb. W połączeniu z zapytaniem agregującym kod wygląda tak.
// 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});
}