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

MongoDB:aggiornamento di una media in un documento con 2 array nidificati

Non puoi usare aggregation per aggiornare un documento, ma puoi sicuramente usarlo per ottenere i dati che desideri utilizzare per un aggiornamento. Prima di tutto, ho notato che ci sono alcuni {} manca intorno al tuo grade oggetto all'interno dei grades Vettore. Potresti voler ricontrollare che la struttura del tuo documento sia come pubblicata. In secondo luogo, ci sono un paio di problemi con la tua query di aggregazione.

  1. Il $avg l'operatore lavora all'interno di un $group clausola, non un $project .
  2. Quando usi $avg , non è necessario utilizzare $sum .
  3. Vuoi fare una media di trucks.grades.grade.grade_number , che contiene effettivamente il valore numerico del voto. Cioè, ti manca il grade tra grades e grade_number .

Se risolvi questi problemi, ricevi una query simile alla seguente:

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

Per il tuo documento di esempio, che restituisce:

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

Ora puoi utilizzare queste informazioni per aggiornare il average_grade campo. Se stai utilizzando MongoDB versione 2.6 o successiva, aggregate il metodo restituirà un cursore. Puoi scorrere il cursore e aggiornare i documenti di conseguenza.

In questo esempio, cerco documenti che hanno un particolare truck_id all'interno dei loro trucks array e procedi con l'aggiornamento di average_grade con quello calcolato dalla query di aggregazione. Puoi modificarlo in base alle tue esigenze. In combinazione con la query di aggregazione, il codice è simile a questo.

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