sql >> Databáze >  >> NoSQL >> MongoDB

Projekt pro filtrování vlastnosti v rámci druhého vnořeného pole

Vzhledem k tomu, že vaším požadavkem je pouze „promítnout“ dokument, aby bylo pole maskováno, ano, agregační rámec je nástroj, jak to udělat. Trochu to trvá, než se zorientujete v procesu při odvíjení polí a rekonstrukci.

Takže to, co jste chtěli, bylo toto:

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

Ale opravdu, pokud máte MongoDB 2.6 nebo vyšší verzi, nemusíte $unwind a $group výsledky zpět dohromady, aby bylo možné toto pole vynechat. Nyní to můžete udělat pomocí $project a $map operátor, který pracuje s poli:

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

Omlouvám se za odsazení, které se trochu posouvá mimo stránku, ale ve srovnání s tím je to stále lépe čitelné.

První $map zpracuje pole otázek na místě a odešle je do vnitřního $map který vrací dokumenty s vnitřním polem odpovědí bez pole "isCorrectAnswer". K reprezentaci prvků používá své vlastní proměnné a použití $ifNull je tam jen proto, že "in" část $map operátor očekává, že vyhodnotí podmínku každého z těchto prvků.

Celkově o něco rychlejší, protože nemusíte procházet přes $unwind a $group operace jen k odstranění pole. Takže se to skutečně stane jen "projekcí", kterou byste mohli očekávat.



  1. jarní relace redis 'Není definována žádná bean s názvem 'springSessionRepositoryFilter'

  2. Získejte n-tý prvek pole v MongoDB

  3. MongoDb Existuje na sloupec

  4. $addToSet implementace pro aktualizaci pole na žádost PATCH