MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Проект за филтриране на свойство във втория вложен масив

Тъй като вашето изискване е просто да „проектирате“ документа, така че полето да е маскирано, да, рамката за агрегиране е инструмент за извършване на това. Отнема малко време, за да се ориентирате в процеса, когато развивате масиви и реконструирате.

И така, това, което искахте, беше следното:

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

Но наистина, ако имате MongoDB 2.6 или по-нова версия, тогава не е необходимо да $unwind и $group резултатите отново заедно, за да пропуснете това поле. Вече можете просто да направите това, като използвате $project и $map оператор, който работи с масиви:

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

Съжалявам за вдлъбнатината, която се превърта малко извън страницата там, но все пак е по-лесна за четене в сравнение.

Първият $map обработва масива с въпроси на място и се подава към вътрешен $map който връща документите с вътрешния масив с отговори без полето "isCorrectAnswer". Той използва свои собствени променливи за представяне на елементите и използването на $ifNull там е само защото частта "in" на $map операторът очаква да оцени условие за всеки от тези елементи.

Като цяло малко по-бързо, тъй като не е нужно да преминавате през $unwind и $group операции само за премахване на полето. Така че наистина се превръща в „проекцията“, която може да очаквате.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Как да създадете уебсайт с лента за търсене, за да правите заявки в база данни на mongo?

  2. MongoDB:резултатът от заявката съответства на всяка стойност в масива

  3. Най-добрият начин за групиране по дата с Mongoid

  4. Преброяване на уникални стойности в масива на модела в MongoDB

  5. сортиране по стойност на вграден обект в Mongodb