การ aggregation บน nested object ที่มี array field (Values) และนับจำนวน (Number) ทำได้โดยแปลง object เป็น array ด้วย $objectToArray แล้ว $unwind และ $group
สร้างคอลเลกชันและข้อมูลตัวอย่าง (โครงสร้างซ้อน)
> db.demo99.insertOne({
'Details': {
'X': { 'Values': [10,30,50], 'Number': 3 },
'Y': { 'Values': [1000, 180], 'Number': 2 }
}
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2d91eab8903cdd865577b9") }
> db.demo99.insertOne({
'Details': {
'X': { 'Values': [100,300,500,6000], 'Number': 4 },
'Y': { 'Values': [10, 20,60], 'Number': 3 }
}
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2d927bb8903cdd865577ba") }
แสดงข้อมูล
> db.demo99.find();
ผลลัพธ์: 2 เอกสาร แต่ละอันมี Details object ที่มี X และ Y (แต่ละตัวมี Values array และ Number)
Query Group Nested Fields นับผลรวม Number
> db.demo99.aggregate([
{ $project: { Count: { $objectToArray: "$Details" } } },
{ $unwind: "$Count" },
{ $group: { _id: "$Count.k", count: { $sum: "$Count.v.Number" } } }
])
คำอธิบายขั้นตอน:
$objectToArray: "$Details": แปลง object {X: {...}, Y: {...}} → array [{k: "X", v: {...}}, {k: "Y", v: {...}}]$unwind: "$Count": แยกแต่ละ key (X, Y) เป็นเอกสารแยกกัน$group: จัดกลุ่มตาม key (k) รวมค่า Number (v.Number)
ผลลัพธ์
{ "_id" : "Y", "count" : 5 }
{ "_id" : "X", "count" : 7 }
การคำนวณ: - X: 3 + 4 = 7 - Y: 2 + 3 = 5
การขยาย: นับจำนวน Values (array length) แทน Number field
db.demo99.aggregate([
{ $project: { Count: { $objectToArray: "$Details" } } },
{ $unwind: "$Count" },
{ $group: {
_id: "$Count.k",
totalValues: { $sum: { $size: "$Count.v.Values" } },
totalNumber: { $sum: "$Count.v.Number" }
}}
])
ใช้ $facet สำหรับหลาย Metrics พร้อมกัน (MongoDB 3.4+)
db.demo99.aggregate([
{ $project: { Count: { $objectToArray: "$Details" } } },
{ $unwind: "$Count" },
{ $facet: {
byKey: [
{ $group: { _id: "$Count.k", count: { $sum: "$Count.v.Number" }}}
],
total: [
{ $group: { _id: null, grandTotal: { $sum: "$Count.v.Number" }}}
]
}}
])
สรุป: $objectToArray + $unwind = เทคนิคหลักสำหรับ flatten dynamic object keys ก่อน aggregation