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

วิธีหาค่าเฉลี่ยของฟิลด์ทั้งหมดด้วย Aggregation Framework ใน MongoDB

การหาค่าเฉลี่ย (Average) ของฟิลด์ทั้งหมดด้วย Aggregation Framework ใน MongoDB

ใช้ $avg operator ภายใน $group stage ของ Aggregation Pipeline เพื่อคำนวณค่าเฉลี่ยของฟิลด์ตัวเลขทั้งหมดใน Collection

ตัวอย่างการสร้างคอลเลกชันและเพิ่มข้อมูล

> db.averageAggregationDemo.insertOne({"PlayerGameScore":45});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9ed66bd628fa4220163b95") }
> db.averageAggregationDemo.insertOne({"PlayerGameScore":55});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9ed671d628fa4220163b96") }
> db.averageAggregationDemo.insertOne({"PlayerGameScore":65});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9ed676d628fa4220163b97") }
> db.averageAggregationDemo.insertOne({"PlayerGameScore":35});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9ed67bd628fa4220163b98") }
> db.averageAggregationDemo.insertOne({"PlayerGameScore":16});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9ed701d628fa4220163b99") }

แสดงข้อมูลทั้งหมด

> db.averageAggregationDemo.find().pretty();

ผลลัพธ์:

{ "_id" : ObjectId("5c9ed66bd628fa4220163b95"), "PlayerGameScore" : 45 }
{ "_id" : ObjectId("5c9ed671d628fa4220163b96"), "PlayerGameScore" : 55 }
{ "_id" : ObjectId("5c9ed676d628fa4220163b97"), "PlayerGameScore" : 65 }
{ "_id" : ObjectId("5c9ed67bd628fa4220163b98"), "PlayerGameScore" : 35 }
{ "_id" : ObjectId("5c9ed701d628fa4220163b99"), "PlayerGameScore" : 16 }

คำนวณค่าเฉลี่ยของ PlayerGameScore ทั้งหมด

> db.averageAggregationDemo.aggregate({ 
    "$group": { 
        "_id": null, 
        "PlayerGameScoreAverage": { "$avg": "$PlayerGameScore" } 
    } 
});

ผลลัพธ์:

{ "_id" : null, "PlayerGameScoreAverage" : 43.2 }

การคำนวณ: (45 + 55 + 65 + 35 + 16) / 5 = 216 / 5 = 43.2

คำอธิบาย Pipeline Stages

  • $group : จับกลุ่มเอกสาร
  • "_id": null : จับกลุ่มทั้งหมดเป็นกลุ่มเดียว (Global Aggregation)
  • $avg : คำนวณค่าเฉลี่ยของ Expression ที่ระบุ
  • "$PlayerGameScore" : อ้างอิง Field PlayerGameScore ของแต่ละ Document

ตัวอย่างขั้นสูง: Group By Field แล้วหาค่าเฉลี่ยแต่ละกลุ่ม

> db.averageAggregationDemo.insertMany([
    { "PlayerName": "John", "PlayerGameScore": 45, "GameType": "Action" },
    { "PlayerName": "Jane", "PlayerGameScore": 55, "GameType": "Action" },
    { "PlayerName": "Bob", "PlayerGameScore": 65, "GameType": "Puzzle" },
    { "PlayerName": "Alice", "PlayerGameScore": 35, "GameType": "Puzzle" }
]);

> db.averageAggregationDemo.aggregate([
    { $group: { 
        _id: "$GameType", 
        averageScore: { $avg: "$PlayerGameScore" },
        count: { $sum: 1 },
        maxScore: { $max: "$PlayerGameScore" },
        minScore: { $min: "$PlayerGameScore" }
    }}
]);

ผลลัพธ์:

{ "_id" : "Action", "averageScore" : 50, "count" : 2, "maxScore" : 55, "minScore" : 45 }
{ "_id" : "Puzzle", "averageScore" : 50, "count" : 2, "maxScore" : 65, "minScore" : 35 }

Accumulator Operators อื่นๆ ใน $group

Operatorคำอธิบายตัวอย่าง
$avgค่าเฉลี่ย{ $avg: "$score" }
$sumผลรวม / นับจำนวน{ $sum: "$score" } หรือ { $sum: 1 }
$minค่าต่ำสุด{ $min: "$score" }
$maxค่าสูงสุด{ $max: "$score" }
$firstค่าแรกในกลุ่ม{ $first: "$score" }
$lastค่าสุดท้ายในกลุ่ม{ $last: "$score" }
$pushสร้าง Array ของค่าทั้งหมด{ $push: "$score" }
$addToSetสร้าง Array ของค่า Unique{ $addToSet: "$score" }
$stdDevPopStandard Deviation (Population){ $stdDevPop: "$score" }
$stdDevSampStandard Deviation (Sample){ $stdDevSamp: "$score" }

การจัดการค่า Null/Missing

  • $avg : ข้ามค่า null และ missing field อัตโนมัติ (ไม่นับในตัวส่วน)
  • $sum : ข้าม null/missing เช่นกัน
  • ถ้าต้องการนับ null เป็น 0 ใช้ $ifNull: { $avg: { $ifNull: ["$score", 0] } }

Best Practices

  • ใช้ _id: null สำหรับ Global Aggregation (ทั้ง Collection)
  • รวม $match ก่อน $group เพื่อ Filter ข้อมูลก่อนคำนวณ (ลด Workload)
  • สร้าง Index บน Field ที่ Group By เพื่อเร่งการ Sort/Group
  • ใช้ allowDiskUse: true ถ้าข้อมูลเยอะเกิน Memory Limit (100MB)
// ตัวอย่าง Pipeline ครบถ้วน
db.collection.aggregate([
    { $match: { "status": "active", "date": { $gte: ISODate("2024-01-01") } } },
    { $group: { 
        _id: null, 
        avgScore: { $avg: "$score" },
        total: { $sum: 1 }
    }},
    { $project: { _id: 0, avgScore: 1, total: 1 } }
], { allowDiskUse: true });