ใช้ $unwind แยกอาร์เรย์ แล้ว $group รวมค่าที่ต้องการ
เมื่อข้อมูลอยู่ในอาร์เรย์ของออบเจ็กต์ซ้อนหลายชั้น ให้ $unwind ทีละระดับ จนได้ระดับที่ต้องการ แล้วค่อยกรองและรวม
ตัวอย่างข้อมูล
> db.demo459.insertOne({
"_id": 1,
"Information": [
{ "Name": "Chris", "_id": new ObjectId(), "details": ["HR"] },
{ "Name": "David", "_id": new ObjectId(), "details": ["Developer"] },
{ "Name": "Bob", "_id": new ObjectId(), "details": ["Account"] }
]
});
Query ดึง details ของ Chris และ Bob
> db.demo459.aggregate([
{ $unwind: "$Information" },
{ $unwind: "$Information.details" },
{ $match: { "Information.Name": { $in: ["Chris", "Bob"] } } },
{ $group: { _id: null, detailList: { $addToSet: "$Information.details" } } }
]);
ผลลัพธ์
{ "_id": null, "detailList": ["Account", "HR"] }
คำอธิบายขั้นตอน
- $unwind: "$Information" - แยกอาร์เรย์ Information เป็นเอกสารแยกต่างหาก
- $unwind: "$Information.details" - แยกอาร์เรย์ details ภายในแต่ละ Information
- $match - กรองเฉพาะ Name เป็น Chris หรือ Bob
- $group + $addToSet - รวมค่า details ที่ไม่ซ้ำกัน
หมายเหตุ
- $addToSet ให้ค่าที่ไม่ซ้ำกัน (unique) ส่วน $push จะเก็บทุกค่า
- หากต้องการเก็บลำดับ ให้ใช้ $push แทน
- _id: null หมายถึงจัดกลุ่มทั้งหมดเป็นกลุ่มเดียว