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

Proyecto para filtrar la propiedad dentro de la segunda matriz anidada

Dado que su requisito es simplemente "proyectar" el documento para que el campo esté enmascarado, sí, el marco de agregación es una herramienta para hacer esto. Sin embargo, se necesita un poco de tiempo para comprender el proceso cuando se desenrollan matrices y se reconstruyen.

Así que lo que querías era esto:

db.collection.aggregate([
    { "$unwind": "$questions" },
    { "$unwind": "$questions.answers" },
    { "$group": { 
        "_id": {
            "_id": "$_id",
            "name": "$name",
            "description": "$description",
            "qid": "$questions._id",
            "question": "$questions.question"
        },
        "answers": {
            "$push": {
                "_id": "$questions.answers._id",
                "answer": "$questions.answers.answer"
            }
        }
    }},
    { "$project": {
        "questions": {
            "_id": "$_id.qid",
            "question": "$_id.question",
            "answers": "$answers"
        }
    }},
    { "$sort": { "_id": 1, "questions._id": 1 } },
    { "$group": {
        "_id": "$_id._id",
        "name": { "$first": "$_id.name" },
        "description": { "$first": "$_id.description" },
        "questions": { "$push": "$questions" }
    }}
])

Pero realmente, si tiene una versión de MongoDB 2.6 o superior, entonces no necesita $desenrollar y $group los resultados juntos para omitir ese campo. Ahora puede hacer esto usando $project y el $map operador que trabaja con arreglos:

db.collection.aggregate([
    { "$project": {
        "name": 1,
        "description": 1,
        "questions": {
            "$map": {
                "input": "$questions",
                "as": "q",
                "in": {
                    "$ifNull": [
                        { 
                            "_id": "$$q._id",
                            "question": "$$q.question",
                            "answers": {
                                "$map": {
                                    "input": "$$q.answers",
                                    "as": "el",
                                    "in": {
                                        "$ifNull": [
                                            { "_id": "$$el._id", "answer": "$$el.answer" },
                                            false
                                        ]
                                    }
                                }
                            }
                        },
                        false
                    ]
                }
            }
        }
    }}
])

Perdón por la sangría que se desplazó un poco fuera de la página, pero aún es más fácil de leer en comparación.

El primer $map procesa la matriz de preguntas en su lugar y alimenta a un $mapa que devuelve los documentos de matriz de respuestas internas sin el campo "isCorrectAnswer". Utiliza sus propias variables para representar los elementos y el uso de $ifNull ahí está solo porque la parte "en" del $mapa el operador espera evaluar una condición en cada uno de esos elementos.

En general, un poco más rápido, ya que no tiene que pasar por $desenrollar y $group operaciones solo para eliminar el campo. Así que realmente se convierte en la "proyección" que podrías esperar.