MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Proyek untuk memfilter properti dalam array bersarang kedua

Karena kebutuhan Anda hanyalah "memproyeksikan" dokumen sehingga bidangnya tertutup, ya kerangka kerja agregasi adalah alat untuk melakukan ini. Perlu sedikit waktu untuk memahami proses saat melepas array dan merekonstruksi.

Jadi yang Anda inginkan adalah ini:

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

Tapi sungguh, jika Anda memiliki MongoDB 2.6 atau versi yang lebih baru maka Anda tidak perlu $unwind dan $group hasilnya kembali bersama untuk menghilangkan bidang itu. Anda sekarang dapat melakukannya menggunakan $project dan $map operator yang bekerja dengan array:

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

Maaf untuk lekukan yang menggulir halaman sedikit di sana, tetapi masih lebih mudah dibaca dengan perbandingan.

$map pertama memproses larik pertanyaan di tempatnya dan diumpankan ke $peta yang mengembalikan dokumen larik jawaban dalam tanpa bidang "isCorrectAnswer". Ia menggunakan variabelnya sendiri untuk mewakili elemen, dan penggunaan $ifNull di sana hanya karena bagian "dalam" $peta operator mengharapkan untuk mengevaluasi kondisi pada setiap elemen tersebut.

Secara keseluruhan sedikit lebih cepat, karena Anda tidak harus melalui $unwind dan $group operasi hanya untuk menghapus lapangan. Jadi itu benar-benar menjadi "proyeksi" yang mungkin Anda harapkan.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Bagaimana Anda bisa menentukan urutan properti dalam objek javascript untuk indeks MongoDB di node.js?

  2. MongoSocketReadException:Mencapai akhir aliran sebelum waktunya (setelah periode tidak aktif)

  3. Mongoose:Tidak dapat mengambil dokumen file dari koleksi .chunk tanpa bidang data

  4. Bisakah $in dan $or saling menggantikan di MongoDB?

  5. Bisakah MongoDB berfungsi ketika ukuran basis data lebih besar dari RAM?