sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB:actualizar un promedio en un documento con 2 matrices anidadas

No puede usar aggregation para actualizar un documento, pero definitivamente puede usarlo para obtener los datos que desea usar para una actualización. En primer lugar, noté que hay algunos {} falta alrededor de su grade objeto dentro de las grades formación. Es posible que desee verificar que la estructura de su documento sea la publicada. En segundo lugar, hay un par de problemas con su consulta de agregación.

  1. El $avg el operador trabaja dentro de un $group cláusula, no un $project .
  2. Cuando usas $avg , no necesita usar $sum .
  3. Desea promediar trucks.grades.grade.grade_number , que en realidad contiene el valor numérico de la calificación. Es decir, te falta grade entre grades y grade_number .

Si resuelve esos problemas, obtendrá una consulta similar a la siguiente:

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

Para su documento de muestra, eso devuelve:

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

Ahora puede usar esta información para actualizar la average_grade campo. Si está utilizando MongoDB versión 2.6 o superior, el aggregate método devolverá un cursor. Puede iterar a través de ese cursor y actualizar los documentos en consecuencia.

En este ejemplo, busco documentos que tengan un truck_id particular. dentro de sus trucks matriz y proceder a actualizar el average_grade con el calculado por la consulta de agregación. Puedes modificarlo para adaptarlo a tus necesidades. Combinado con la consulta de agregación, el código se ve así.

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