MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB:Aktualisieren eines Durchschnitts in einem Dokument mit 2 verschachtelten Arrays

Sie können aggregation nicht verwenden um ein Dokument zu aktualisieren, aber Sie können es definitiv verwenden, um die Daten zu erhalten, die Sie für ein Update verwenden möchten. Als erstes ist mir aufgefallen, dass es einige {} gibt fehlt um Ihre grade Objekt innerhalb der grades Reihe. Möglicherweise möchten Sie noch einmal überprüfen, ob Ihre Dokumentstruktur wie gebucht ist. Zweitens gibt es einige Probleme mit Ihrer Aggregationsabfrage.

  1. Der $avg -Operator arbeitet innerhalb einer $group -Klausel, kein $project .
  2. Wenn Sie $avg verwenden , müssen Sie $sum nicht verwenden .
  3. Sie möchten trucks.grades.grade.grade_number mitteln , die eigentlich den numerischen Wert der Note enthält. Das heißt, Ihnen fehlt grade zwischen grades und grade_number .

Wenn Sie diese Probleme beheben, erhalten Sie eine Abfrage ähnlich der folgenden:

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

Für Ihr Beispieldokument gibt das zurück:

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

Jetzt können Sie diese Informationen verwenden, um average_grade zu aktualisieren aufstellen. Wenn Sie MongoDB Version 2.6 oder höher verwenden, wird die Datei aggregate Methode gibt einen Cursor zurück. Sie können diesen Cursor durchlaufen und die Dokumente entsprechend aktualisieren.

In diesem Beispiel suche ich nach Dokumenten, die eine bestimmte truck_id haben in ihren trucks -Array und fahren Sie mit der Aktualisierung von average_grade fort mit der von der Aggregationsabfrage berechneten. Sie können es an Ihre Bedürfnisse anpassen. Kombiniert mit der Aggregationsabfrage sieht der Code so aus.

// 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});
}