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.