การประมวลผลอาร์เรย์ซ้อนหลายชั้นด้วย Aggregation Pipeline
ใช้ $addFields, $map, $let, $arrayElemAt, $cond เพื่อแปลงและกรองข้อมูลในอาร์เรย์ซ้อนหลายระดับ
ตัวอย่างข้อมูล (3 ระดับ)
> db.demo441.insertOne({
"Name": "David", "Age": 21,
"details": [{
"id": 1, "CountryName": "US",
"details1": [
{ "SubjectName": "MySQL", "Score": 56 },
{ "SubjectName": "MongoDB", "Score": 78 }
]
}]
});
Query Aggregate อาร์เรย์ซ้อน
> db.demo441.aggregate([{
$addFields: {
ResultOfDetails: {
$map: {
input: "$details",
as: "output",
in: {
id: "$$output.id",
CountryName: "$$output.CountryName",
details1: {
$let: {
vars: {
last: { $arrayElemAt: ["$$output.details1", -1] }
},
in: {
$cond: [
{ $eq: ["$$last.Score", 78] },
["$$last"],
[]
]
}
}
}
}
}
}
}
}]).pretty();
ผลลัพธ์
{
"_id": ObjectId(...), "Name": "David", "Age": 21,
"details": [{ "id": 1, "CountryName": "US", "details1": [{ "SubjectName": "MySQL", "Score": 56 }, { "SubjectName": "MongoDB", "Score": 78 }] }],
"ResultOfDetails": [{ "id": 1, "CountryName": "US", "details1": [{ "SubjectName": "MongoDB", "Score": 78 }] }]
}
คำอธิบาย Operator สำคัญ
- $map - วนลูปแปลงแต่ละอิลิเมนต์ในอาร์เรย์
- $let - กำหนดตัวแปรชั่วคราว (vars) เพื่อใช้ซ้ำ
- $arrayElemAt: [..., -1] - ดึงอิลิเมนต์สุดท้ายของอาร์เรย์
- $cond - เงื่อนไข if-then-else
การประยุกต์
รูปแบบนี้เหมาะสำหรับ: การกรองรายวิชาที่ผ่าน/ไม่ผ่าน, ดึงข้อมูลล่าสุดในแต่ละกลุ่ม, แปลงโครงสร้างข้อมูลซ้อนซับซ้อน