Dado un conjunto de preguntas que se han vinculado de la encuesta y el id de la 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 la categoría media 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 la categoría promedios (nota: esto es diferente de simplemente un promedio de todas las preguntas)? Supongo que me gustaría hacer varias operaciones del grupo, pero esta 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
}
>

1 Comentario

  1. 32

    Es importante entender que las operaciones en el argumento de agregar() forma un tubería. Esto significaba que la entrada a cualquier elemento de la tubería es el flujo de los documentos producidos por el elemento anterior en la tubería.

    En tu ejemplo, tu 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 pipline está viendo una serie de documentos en los que la única claves son «_id» y «avg_score». Las teclas «category_id» y «puntuación» ya no existen en esta secuencia de documento.

    Si quieres más agregado en esta corriente, tendrás que agregado a través de las teclas que se observan en esta etapa en la tubería. Puesto que usted desea que el promedio de los promedios, que usted necesita para poner en un solo valor constante para el campo _id, de modo que todos los de la entrada de documentos que se agrupan en un único 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, se produce la siguiente salida:

     {
        "result" : [
            {
            "_id" : "all",
            "avg_score" : 4.75
            }
        ],
        "ok" : 1
     }
    • Hmmm, no sabía que se podía utilizar una constante. Asumo que este enfoque no trabajo para agrupar en un nivel aún más alto. Gracias, parece que se va a trabajar para este caso de uso a pesar de que
    • Si desea agrupar en un nivel superior, usted sólo tiene que asegurarse de que las claves correspondientes se proyectan en la secuencia de documento por el primer elemento de la tubería. Si usted tiene un hormigón de ejemplo, siéntase libre de publicar otra pregunta.

Dejar respuesta

Please enter your comment!
Please enter your name here