Du kan inte använda aggregation
för att uppdatera ett dokument, men du kan definitivt använda det för att få de data du vill använda för en uppdatering. Först och främst märkte jag att det finns några {}
saknas runt ditt grade
objekt i grades
array. Du kanske vill dubbelkolla att din dokumentstruktur är som den har lagts upp. För det andra finns det ett par problem med din aggregeringsfråga.
$avg
operatorn arbetar i en$group
sats, inte ett$project
.- När du använder
$avg
, du behöver inte använda$sum
. - Du vill ha ett genomsnitt av
trucks.grades.grade.grade_number
, som faktiskt håller betygets numeriska värde. Det vill säga, du saknargrade
mellangrade
ochgrade_number
.
Om du löser dessa problem får du en fråga som liknar följande:
db.col.aggregate([
{ "$unwind": "$trucks" },
{ "$unwind": "$trucks.grades" },
{ "$group":
{
"_id": "$trucks.truck_id",
"average_grade": { "$avg": "$trucks.grades.grade_number" }
}
}
]);
För ditt exempeldokument returnerar det:
{ "_id" : "TEB5572", "average_grade" : 4 }
{ "_id" : "TEB7622", "average_grade" : 4 }
Nu kan du använda denna information för att uppdatera average_grade
fält. Om du använder MongoDB version 2.6 eller högre, aggregate
metod returnerar en markör. Du kan iterera genom den markören och uppdatera dokumenten därefter.
I det här exemplet söker jag efter dokument som har ett särskilt truck_id
inuti sina trucks
array och fortsätt med att uppdatera average_grade
med den som beräknas av aggregeringsfrågan. Du kan modifiera den för att passa dina behov. I kombination med aggregeringsfrågan ser koden ut så här.
// 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});
}