บทความนี้สาธิตการใช้ Aggregation Framework โดยเฉพาะ $addFields และ $avg เพื่อคำนวณค่าเฉลี่ยของคะแนนใน Array แล้วเพิ่มเป็นฟิลด์ใหม่ใน Document เดียวกัน
สร้างข้อมูลตัวอย่าง
> db.averageOfRatingsInArrayDemo.insertOne(
{
"StudentDetails":[
{ "StudentId":1, "StudentScore":45 },
{ "StudentId":2, "StudentScore":58 },
{ "StudentId":3, "StudentScore":67 }
]
}
);
{ "acknowledged" : true, "insertedId" : ObjectId("5cd427dc2cba06f46efe9ee4") }
แสดงข้อมูลต้นฉบับ
> db.averageOfRatingsInArrayDemo.find().pretty();
{
"_id" : ObjectId("5cd427dc2cba06f46efe9ee4"),
"StudentDetails" : [
{ "StudentId" : 1, "StudentScore" : 45 },
{ "StudentId" : 2, "StudentScore" : 58 },
{ "StudentId" : 3, "StudentScore" : 67 }
]
}
คำนวณค่าเฉลี่ยและเพิ่มฟิลด์ StudentScoreAverage
> db.averageOfRatingsInArrayDemo.aggregate([
{ $addFields : {
StudentScoreAverage : { $avg : "$StudentDetails.StudentScore" }
}}
]);
ผลลัพธ์
{
"_id" : ObjectId("5cd427dc2cba06f46efe9ee4"),
"StudentDetails" : [
{ "StudentId" : 1, "StudentScore" : 45 },
{ "StudentId" : 2, "StudentScore" : 58 },
{ "StudentId" : 3, "StudentScore" : 67 }
],
"StudentScoreAverage" : 56.666666666666664
}
คำอธิบาย Operator ที่ใช้
- $addFields: เพิ่มฟิลด์ใหม่เข้าไปใน Document โดยคงฟิลด์เดิมไว้ทั้งหมด
- $avg: คำนวณค่าเฉลี่ยของค่าตัวเลข ในที่นี้เข้าถึง
$StudentDetails.StudentScoreจะได้ Array ของคะแนน [45, 58, 67] - Dot Notation ใน Expression:
"$StudentDetails.StudentScore"ดึงค่า StudentScore จากทุก Object ใน Array
ตัวอย่างเพิ่มเติม: คำนวณหลายสถิติพร้อมกัน
db.collection.aggregate([
{ $addFields: {
scoreAvg: { $avg: "$StudentDetails.StudentScore" },
scoreMin: { $min: "$StudentDetails.StudentScore" },
scoreMax: { $max: "$StudentDetails.StudentScore" },
scoreCount: { $size: "$StudentDetails" }
}}
]);
หมายเหตุ
Aggregation Pipeline ไม่เปลี่ยนข้อมูลใน Database โดยตรง หากต้องการบันทึกต้องใช้ $merge หรือ $out หรือนำผลลัพธ์ไป Update กลับด้วยโปรแกรม