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

Projekt for at filtrere egenskab inden for det andet indlejrede array

Da dit krav er bare at "projektere" dokumentet, så feltet er maskeret, ja aggregeringsrammen er et værktøj til at gøre dette. Det kræver dog lidt at få styr på processen, når du afvikler arrays og rekonstruerer.

Så det, du ønskede, var dette:

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" }
    }}
])

Men virkelig, hvis du har en MongoDB 2.6 eller nyere version, behøver du ikke $unwind og $group resultaterne sammen igen for at udelade dette felt. Du kan nu bare gøre dette ved at bruge $project og $map operator, der arbejder med arrays:

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
                    ]
                }
            }
        }
    }}
])

Beklager, at indrykket ruller lidt af siden der, men det er stadig lettere at læse ved sammenligning.

Den første $map behandler spørgsmålsarrayet på plads og feeds til en indre $map der returnerer de indre svar-array-dokumenter uden feltet "isCorrectAnswer". Den bruger sine egne variabler til at repræsentere elementerne og brugen af ​​$ifNull der er bare fordi "in"-delen af ​​$map operatør forventer at evaluere en betingelse på hvert af disse elementer.

Samlet set lidt hurtigere, da du ikke behøver at gå gennem $unwind og $group operationer bare for at fjerne feltet. Så det bliver i virkeligheden bare den "projektion", som du kunne forvente.



  1. MongoDB-skår og ubalancerede aggregeringsbelastninger

  2. mongorestore fra enkeltstående til replicaset

  3. Filtrer efter dato ved hjælp af et idObject

  4. Analyser ydeevnen af ​​en forespørgsel - mongoDB