การรวมหลาย array fields ในเอกสารเดียวกันให้กลายเป็น array เดียว ทำได้ด้วย $setUnion ร่วม $filter ใน $project stage
สร้างคอลเลกชันและข้อมูลตัวอย่าง
> db.demo119.insertOne({
"_id": 101,
"WebDetails": [
{ "ImagePath": "/all/image1", "isCorrect": "false" },
{ "ImagePath": "/all/image2", "isCorrect": "true" }
],
"ClientDetails": [
{ "Name": "Chris", "isCorrect": "false" },
{ "Name": "David", "isCorrect": "true" }
]
});
{ "acknowledged" : true, "insertedId" : 101 }
แสดงข้อมูล
> db.demo119.find();
ผลลัพธ์: มี WebDetails และ ClientDetails arrays
Query รวม Arrays และ Filter isCorrect="false"
> db.demo119.aggregate([
{ "$project": {
"AllDetails": {
"$filter": {
"input": {
"$setUnion": [
{ "$ifNull": ["$WebDetails", []] },
{ "$ifNull": ["$ClientDetails", []] }
]
},
"as": "out",
"cond": { "$eq": ["$$out.isCorrect", "false"] }
}
}
}},
{ "$match": { "AllDetails.0": { "$exists": true } } }
])
คำอธิบายขั้นตอน:
$ifNull: ["$WebDetails", []]: ป้องกัน error หาก field หายไป (คืน array ว่าง)$setUnion: รวม 2 arrays เป็น array เดียว (ลบ duplicate ตาม object ทั้งหมด)$filter: กรองเฉพาะ element ที่ isCorrect="false"$match: {"AllDetails.0": {$exists: true}}: กรองเอกสารที่ AllDetails ไม่ว่าง
ผลลัพธ์
{ "_id" : 101, "AllDetails" : [
{ "ImagePath" : "/all/image1", "isCorrect" : "false" },
{ "Name" : "Chris", "isCorrect" : "false" }
] }
รวม image1 (จาก WebDetails) และ Chris (จาก ClientDetails) ที่ isCorrect="false"
ข้อควรระวังของ $setUnion
- ลบ duplicate ตาม object ทั้งหมด (ทุก field ตรงกัน)
- ไม่ preserve order
- หาก object structure ต่างกัน (ImagePath vs Name) จะไม่ถูกลบซ้ำ
วิธีอื่น: $concatArrays (MongoDB 4.4+) - รวมโดยไม่ลบซ้ำ
db.demo119.aggregate([
{ $project: {
AllDetails: {
$filter: {
input: { $concatArrays: ["$WebDetails", "$ClientDetails"] },
cond: { $eq: ["$$this.isCorrect", "false"] }
}
}
}}
])
กรณีต้องการ Merge Objects (รวม field)
หาก array ทั้งสองมีโครงสร้างเดียวกัน และต้องการ merge โดย key:
db.collection.aggregate([
{ $project: {
merged: {
$reduce: {
input: { $concatArrays: ["$array1", "$array2"] },
initialValue: {},
in: { $mergeObjects: ["$$value", "$$this"] }
}
}
}}
])
สรุป: $setUnion + $filter = รวมและกรอง | $concatArrays + $filter = รวมทุกอย่างแล้วกรอง