การคำนวณผลรวม (sum) ของหลาย field ภายใน array of objects ทุกเอกสาร ใช้ $unwind แยก array แล้ว $group จัดกลุ่มตามชื่อ และ $sum สะสมค่าแต่ละ field
สร้างคอลเลกชันและข้อมูลตัวอย่าง
> db.demo117.insertOne({
ID: 101,
Details: [
{ Name: 'Chris', Value1: 20, Value2: 30, Value3: 10 },
{ Name: 'David', Value1: 10, Value2: 50, Value3: 30 }
]
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2f02ced8f64a552dae6361") }
> db.demo117.insertOne({
ID: 102,
Details: [
{ Name: 'Chris', Value1: 20, Value2: 10, Value3: 20 },
{ Name: 'David', Value1: 30, Value2: 40, Value3: 10 }
]
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2f02ced8f64a552dae6362") }
แสดงข้อมูล
> db.demo117.find();
ผลลัพธ์: 2 เอกสาร แต่ละอันมี Details array 2 elements (Chris, David)
Query Aggregate Sum ทุก Field แยกตาม Name
> db.demo117.aggregate([
{ $unwind: "$Details" },
{ $group: {
_id: "$Details.Name",
"Value1": { $sum: "$Details.Value1" },
"Value2": { $sum: "$Details.Value2" },
"Value3": { $sum: "$Details.Value3" }
}}
])
คำอธิบาย:
$unwind: "$Details": แยก array Details → 4 เอกสาร (2 ต่อ 1 doc เดิม)$group: จัดกลุ่มตาม Details.Name (Chris, David)$sum: "$Details.Value1": สะสม Value1 ของแต่ละกลุ่ม
ผลลัพธ์
{ "_id" : "David", "Value1" : 40, "Value2" : 90, "Value3" : 40 }
{ "_id" : "Chris", "Value1" : 40, "Value2" : 40, "Value3" : 30 }
การคำนวณ: - Chris: V1=20+20=40, V2=30+10=40, V3=10+20=30 - David: V1=10+30=40, V2=50+40=90, V3=30+10=40 ✓
Dynamic Fields: Sum ทุก Field โดยไม่ระบุชื่อ (Advanced)
หากไม่รู้ล่วงหน้ามี field ใดบ้าง ใช้ $objectToArray + $group + $mergeObjects:
db.demo117.aggregate([
{ $unwind: "$Details" },
{ $project: {
name: "$Details.Name",
values: { $objectToArray: "$Details" }
}},
{ $unwind: "$values" },
{ $match: { "values.k": { $ne: "Name" } }},
{ $group: {
_id: { name: "$name", key: "$values.k" },
sum: { $sum: "$values.v" }
}},
{ $group: {
_id: "$_id.name",
fields: { $push: { k: "$_id.key", v: "$sum" } }
}},
{ $project: {
_id: 1,
sums: { $arrayToObject: "$fields" }
}}
])
Performance Tips
- สร้าง index บน field ที่ $unwind บ่อย (หากเป็น array ใหญ่)
- ใช้ $match ก่อน $unwind เพื่อลดจำนวน documents
- พิจารณา $facet หากต้องการหลายมุมมองพร้อมกัน
สรุป: $unwind → $group + $sum = pattern มาตรฐานสำหรับ aggregate sum ใน array of objects