ใช้ $filter ร่วม $project ใน aggregation pipeline เพื่อดึงเฉพาะฟิลด์ที่ต้องการจาก nested array documents สร้างคอลเลกชันตัวอย่าง (nested 3 ระดับ):
> db.demo342.insertOne({
"Id": "101",
"details1" : {
"details2" : [
{
"details3" : [
{ "Name": "Mike", "CountryName" : "US" },
{ "Name": "David", "CountryName" : "AUS" },
{ "Name": "Bob", "CountryName" : "UK" }
]
}
]
}
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e53ef99f8647eb59e5620a9") }
แสดงข้อมูล:
> db.demo342.find();
คิวรี aggregation ดึงเฉพาะรายการที่ Name = "Bob" ในระดับลึกที่สุด:
> db.demo342.aggregate([
{ "$project": {
"details1": {
"details2": {
"$filter": {
"input": {
"$map": {
"input": "$details1.details2",
"in": {
"details3": {
"$filter": {
"input": "$$this.details3",
"cond": { "$eq": ["$$this.Name", "Bob"] }
}
}
}
}
},
"cond": { "$ne": ["$$this.details3", []] }
}
}
}
}}
])
ผลลัพธ์ (ได้เฉพาะ Bob):
{ "_id" : ObjectId("5e53ef99f8647eb59e5620a9"), "details1" : { "details2" : [ { "details3" : [ { "Name" : "Bob", "CountryName" : "UK" } ] } ] } }
คำอธิบาย Pipeline
$map: วนลูปผ่าน details2 สร้างโครงสร้างใหม่$filter(ภายใน): กรอง details3 ให้เหลือเฉพาะ Name = "Bob"$filter(ภายนอก): กรอง details2 ให้เหลือเฉพาะที่ details3 ไม่ใช่ array ว่าง$$thisอ้างอิงสมาชิกปัจจุบันใน $map/$filter
หมายเหตุ
MongoDB 4.4+ มี $reduce และ $function ที่อาจทำให้ query สั้นลง สำหรับ nested array หลายระดับ ควรพิจารณา schema design ใหม่ให้ flat กว่านี้เพื่อ query ง่ายขึ้น