ใช้ aggregate() ร่วมกับ $unwind หลายขั้นตอน เพื่อ "แบน" (flatten) อาร์เรย์ซ้อนหลายชั้น แล้วจึงกรอง/เรียงลำดับ/จำกัดจำนวนผลลัพธ์
ตัวอย่างข้อมูลโครงสร้างซ้อนหลายชั้น
> db.demo70.insertOne({
"first": [
{
"details": {
"second": [
{ "StudentDetails": { "Score": 10 } },
{ "StudentDetails": { "Score": 20 } },
{ "StudentDetails": { "Score": 30 } }
]
}
},
{
"details": {
"second": [
{ "StudentDetails": { "Score": 11 } },
{ "StudentDetails": { "Score": 18 } },
{ "StudentDetails": { "Score": 29 } }
]
}
}
]
});
{ "acknowledged": true, "insertedId": ObjectId("5e29ad4d0912fae76b13d76d") }
แสดงโครงสร้างข้อมูล
> db.demo70.find().pretty();
ผลลัพธ์ (โครงสร้างซ้อน 3 ชั้น: first → details.second → StudentDetails.Score)
{
"_id": ObjectId("5e29ad4d0912fae76b13d76d"),
"first": [
{
"details": {
"second": [
{ "StudentDetails": { "Score": 10 } },
{ "StudentDetails": { "Score": 20 } },
{ "StudentDetails": { "Score": 30 } }
]
}
},
{
"details": {
"second": [
{ "StudentDetails": { "Score": 11 } },
{ "StudentDetails": { "Score": 18 } },
{ "StudentDetails": { "Score": 29 } }
]
}
}
]
}
Aggregate Pipeline: $unwind 2 ครั้ง + เรียงลำดับ + จำกัด 3 อันดับแรก
> db.demo70.aggregate([
{ $unwind: "$first" },
{ $unwind: "$first.details.second" },
{ $sort: { "first.details.second.StudentDetails.Score": -1 } },
{ $limit: 3 },
{ $replaceRoot: { newRoot: "$first.details.second.StudentDetails" } },
{ $sort: { "Score": 1 } }
]);
ผลลัพธ์ (คะแนนสูงสุด 3 อันดับ แล้วเรียงน้อยไปมาก)
{ "Score": 20 }
{ "Score": 29 }
{ "Score": 30 }
คำอธิบาย Pipeline:
$unwind: "$first"- แยกอาร์เรย์ first ออกเป็นเอกสารแยกกัน$unwind: "$first.details.second"- แยกอาร์เรย์ second ออกเป็นเอกสารแยกกัน$sort- เรียงคะแนนจากมากไปน้อย$limit: 3- เอาแค่ 3 อันดับแรก$replaceRoot- ยกฟิลด์ StudentDetails ขึ้นมาเป็นรากเอกสาร$sort: { "Score": 1 }- เรียงผลลัพธ์สุดท้ายจากน้อยไปมาก