กรอง Sub-documents หลายชุดพร้อมกันด้วย aggregate()
บทความนี้สาธิตวิธีการกรองข้อมูลจาก Sub-documents หลายชุด (multiple sub-document arrays) ในเอกสารเดียวกัน โดยใช้ Aggregation Pipeline หลายขั้นตอน: $match, $unwind, $group, $project
ขั้นตอนที่ 1: สร้าง Collection และเพิ่มข้อมูลตัวอย่าง
สร้าง collection ชื่อ demo200 ซึ่งมีอาร์เรย์ 2 ชุด คือ details1 และ details2 แต่ละชุดมีฟิลด์ isActive เพื่อระบุสถานะ
> db.demo200.insertOne({
"Id": "101",
"details1": [
{ "isActive": true, "SubjectName": "MySQL" },
{ "isActive": false, "SubjectName": "Java" }
],
"details2": [
{ "isActive": false, "Name": "David" },
{ "isActive": true, "Name": "Mike" }
]
});
{ "acknowledged": true, "insertedId": ObjectId("5e3c374f03d395bdc21346e4") }
ขั้นตอนที่ 2: แสดงข้อมูลทั้งหมด
> db.demo200.find();
ผลลัพธ์:
{ "_id": ObjectId("5e3c374f03d395bdc21346e4"), "Id": "101", "details1": [
{ "isActive": true, "SubjectName": "MySQL" },
{ "isActive": false, "SubjectName": "Java" }
], "details2": [
{ "isActive": false, "Name": "David" },
{ "isActive": true, "Name": "Mike" }
] }
ขั้นตอนที่ 3: Aggregation Pipeline สำหรับกรอง Sub-documents หลายชุด
Pipeline ประกอบด้วยขั้นตอนดังนี้:
$match- กรองเอกสารหลักที่มีId: "101"และทั้ง 2 อาร์เรย์มีisActive: trueอย่างน้อย 1 รายการ$unwind: "$details1"- แยกอาร์เรย์ details1$unwind: "$details2"- แยกอาร์เรย์ details2$match- กรองเฉพาะรายการที่details1.isActive: trueและdetails2.isActive: true$group- รวมกลับเป็นอาร์เรย์ด้วย$addToSet$project- จัดรูปแบบเอาต์พุตสุดท้าย
> var out = [
{ "$match": { "Id": "101", "details1.isActive": true, "details2.isActive": true } },
{ "$unwind": "$details1" },
{ "$unwind": "$details2" },
{ "$match": { "details1.isActive": true, "details2.isActive": true } },
{ "$group": {
"_id": { "_id": "$_id", "Id": "$Id" },
"details2": { "$addToSet": "$details2" },
"details1": { "$addToSet": "$details1" }
}},
{ "$project": { "_id": 0, "Id": "$_id.Id", "details2": 1, "details1": 1 } }
];
> db.demo200.aggregate(out)
ผลลัพธ์ที่ได้
{ "details2": [{ "isActive": true, "Name": "Mike" }], "details1": [{ "isActive": true, "SubjectName": "MySQL" }], "Id": "101" }
สรุป: เทคนิคนี้เหมาะสำหรับกรณีที่ต้องกรองข้อมูลจากอาร์เรย์หลายชุดพร้อมกัน และต้องการผลลัพธ์ที่รวมเฉพาะรายการที่ตรงเงื่อนไขจากทุกชุด