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

MongoDB Aggregate: ผลรวมค่าใน List of Dictionaries ทุกเอกสาร

การคำนวณผลรวม (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" }
  }}
])

คำอธิบาย:

  1. $unwind: "$Details": แยก array Details → 4 เอกสาร (2 ต่อ 1 doc เดิม)
  2. $group: จัดกลุ่มตาม Details.Name (Chris, David)
  3. $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