sql >> Database teknologi >  >> NoSQL >> MongoDB

MongoDB:Opdatering af et gennemsnit i et dokument med 2 indlejrede arrays

Du kan ikke bruge aggregation at opdatere et dokument, men du kan helt sikkert bruge det til at få de data, du vil bruge til en opdatering. Først og fremmest har jeg bemærket, at der er nogle {} mangler omkring din grade objekt inde i grades array. Du vil måske dobbelttjekke, at din dokumentstruktur er som den er bogført. For det andet er der et par problemer med din aggregeringsforespørgsel.

  1. $avg operatør arbejder i en $group klausul, ikke et $project .
  2. Når du bruger $avg , behøver du ikke bruge $sum .
  3. Du vil have et gennemsnit af trucks.grades.grade.grade_number , som faktisk holder karakterens numeriske værdi. Det vil sige, du mangler grade mellem grades og grade_number .

Hvis du løser disse problemer, får du en forespørgsel, der ligner følgende:

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

For dit eksempeldokument returnerer det:

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

Nu kan du bruge disse oplysninger til at opdatere average_grade Mark. Hvis du bruger MongoDB version 2.6 eller nyere, er aggregate metoden returnerer en markør. Du kan iterere gennem markøren og opdatere dokumenterne i overensstemmelse hermed.

I dette eksempel søger jeg efter dokumenter, der har et bestemt truck_id inde i deres trucks array og fortsæt med at opdatere average_grade med den, der er beregnet af aggregeringsforespørgslen. Du kan ændre det, så det passer til dine behov. Kombineret med aggregeringsforespørgslen ser koden sådan ud.

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



  1. Den nemmeste måde at konfigurere Embedded MongoDB

  2. MongoDB $addToSet

  3. Sådan flettes matrixfelt i dokument i Mongo-aggregation

  4. Hvad er den bedste måde at bruge Redis i et multi-threaded Rails-miljø? (Puma / Sidekiq)