sirve que para funcion examples ejemplo consultas complejas avg avanzado agregados mongodb

que - mongodb avanzado



Múltiples operaciones grupales utilizando el marco de agregación Mongo. (1)

Dado un conjunto de preguntas que han vinculado la encuesta y la identificación de categoría:

> db.questions.find().toArray(); [ { "_id" : ObjectId("4fda05bc322b1c95b531ac25"), "id" : 1, "name" : "Question 1", "category_id" : 1, "survey_id" : 1, "score" : 5 }, { "_id" : ObjectId("4fda05cb322b1c95b531ac26"), "id" : 2, "name" : "Question 2", "category_id" : 1, "survey_id" : 1, "score" : 3 }, { "_id" : ObjectId("4fda05d9322b1c95b531ac27"), "id" : 3, "name" : "Question 3", "category_id" : 2, "survey_id" : 1, "score" : 4 }, { "_id" : ObjectId("4fda4287322b1c95b531ac28"), "id" : 4, "name" : "Question 4", "category_id" : 2, "survey_id" : 1, "score" : 7 } ]

Puedo encontrar el promedio de la categoría con:

db.questions.aggregate( { $group : { _id : "$category_id", avg_score : { $avg : "$score" } } } ); { "result" : [ { "_id" : 1, "avg_score" : 4 }, { "_id" : 2, "avg_score" : 5.5 } ], "ok" : 1 }

¿Cómo puedo obtener el promedio de los promedios de categoría (tenga en cuenta que esto es diferente a simplemente promediar todas las preguntas)? Asumiría que haría varias operaciones de grupo pero esto falla:

> db.questions.aggregate( ... { $group : { ... _id : "$category_id", ... avg_score : { $avg : "$score" }, ... }}, ... { $group : { ... _id : "$survey_id", ... avg_score : { $avg : "$score" }, ... }} ... ); { "errmsg" : "exception: the _id field for a group must not be undefined", "code" : 15956, "ok" : 0 } >


Es importante entender que las operaciones en el argumento de aggregate () forman una tubería . Esto significó que la entrada a cualquier elemento de la tubería es el flujo de documentos producidos por el elemento anterior en la tubería.

En su ejemplo, su primera consulta crea una tubería de documentos que se parecen a esto:

{ "_id" : 2, "avg_score" : 5.5 }, { "_id" : 1, "avg_score" : 4 }

Esto significa que el segundo elemento de la línea de tubería es ver una serie de documentos donde las únicas claves son "_id" y "avg_score". Las claves "category_id" y "score" ya no existen en este flujo de documentos.

Si desea agregar más en esta secuencia, tendrá que agregar usando las claves que se ven en esta etapa en la tubería. Como desea promediar los promedios, debe poner un valor constante único para el campo _id, de modo que todos los documentos de entrada se agrupen en un solo resultado.

El siguiente código produce el resultado correcto:

db.questions.aggregate( { $group : { _id : "$category_id", avg_score : { $avg : "$score" }, } }, { $group : { _id : "all", avg_score : { $avg : "$avg_score" }, } } );

Cuando se ejecuta, produce el siguiente resultado:

{ "result" : [ { "_id" : "all", "avg_score" : 4.75 } ], "ok" : 1 }