Nemůžete použít aggregation
k aktualizaci dokumentu, ale rozhodně jej můžete použít k získání dat, která chcete použít pro aktualizaci. Nejprve jsem si všiml, že existují nějaké {}
chybí kolem vašeho grade
objekt uvnitř grade
pole. Možná budete chtít znovu zkontrolovat, zda struktura vašeho dokumentu odpovídá zaúčtování. Za druhé, existuje několik problémů s vaším agregačním dotazem.
$avg
operátor pracuje uvnitř$group
klauzule, nikoli$project
.- Když použijete
$avg
, nemusíte používat$sum
. - Chcete vytvořit průměr
trucks.grades.grade.grade_number
, která ve skutečnosti obsahuje číselnou hodnotu známky. To znamená, že vám chybígrade
mezigrades
agrade_number
.
Pokud tyto problémy vyřešíte, zobrazí se dotaz podobný následujícímu:
db.col.aggregate([
{ "$unwind": "$trucks" },
{ "$unwind": "$trucks.grades" },
{ "$group":
{
"_id": "$trucks.truck_id",
"average_grade": { "$avg": "$trucks.grades.grade_number" }
}
}
]);
Pro váš vzorový dokument to vrátí:
{ "_id" : "TEB5572", "average_grade" : 4 }
{ "_id" : "TEB7622", "average_grade" : 4 }
Nyní můžete tyto informace použít k aktualizaci average_grade
pole. Pokud používáte MongoDB verze 2.6 nebo vyšší, aggregate
metoda vrátí kurzor. Tímto kurzorem můžete iterovat a podle toho aktualizovat dokumenty.
V tomto příkladu hledám dokumenty, které mají konkrétní truck_id
v jejich trucks
pole a pokračujte v aktualizaci average_grade
s hodnotou vypočítanou agregačním dotazem. Můžete jej upravit tak, aby vyhovoval vašim potřebám. V kombinaci s agregačním dotazem vypadá kód takto.
// 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});
}