Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MongoDB

MongoDB Aggregation: จัดกลุ่ม Nested Fields นับค่าใน Array

การ 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" } } }
])

คำอธิบายขั้นตอน:

  1. $objectToArray: "$Details": แปลง object {X: {...}, Y: {...}} → array [{k: "X", v: {...}}, {k: "Y", v: {...}}]
  2. $unwind: "$Count": แยกแต่ละ key (X, Y) เป็นเอกสารแยกกัน
  3. $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