การหาค่าสูงสุด (maximum) แยกตามกลุ่ม (เช่นชื่อที่ซ้ำกัน) ใน MongoDB สามารถใช้ method group() (legacy) หรือ aggregate() พร้อม $max (แนะนำ)
สร้างคอลเลกชันและข้อมูลตัวอย่าง (มีชื่อซ้ำ)
> db.demo114.insertOne({"Score":60,"Name":"Chris"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2efc57d8f64a552dae6354") }
> db.demo114.insertOne({"Score":87,"Name":"Chris"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2efc5ad8f64a552dae6355") }
> db.demo114.insertOne({"Score":45,"Name":"David"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2efc5dd8f64a552dae6356") }
> db.demo114.insertOne({"Score":67,"Name":"Chris"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2efc68d8f64a552dae6357") }
> db.demo114.insertOne({"Score":38,"Name":"David"});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2efc74d8f64a552dae6358") }
แสดงข้อมูลทั้งหมด
> db.demo114.find();
ผลลัพธ์: Chris มี 3 ระดับ (60, 87, 67), David มี 2 ระดับ (45, 38)
Query แบบ Legacy: ใช้ group()
> db.demo114.group(
{key: {Name:true},
reduce: function(c,p) {
if (p.maximumScore < c.Score) {
p.maximumScore = c.Score;
}
},
initial: { maximumScore: 0 }}
);
คำอธิบาย group() (Deprecated):
key: {Name:true}: จัดกลุ่มตาม Nameinitial: ค่าเริ่มต้นของ accumulator (p)reduce: function(current, accumulator) - เรียกทุก document ในกลุ่ม- ข้อจำกัด: ไม่ทำงานกับ sharded collections, จำกัด result size 10k docs
ผลลัพธ์ group()
[
{ "Name" : "Chris", "maximumScore" : 87 },
{ "Name" : "David", "maximumScore" : 45 }
]
วิธีใหม่แนะนำ: Aggregate $max (MongoDB 2.2+)
db.demo114.aggregate([
{ $group: {
_id: "$Name",
maximumScore: { $max: "$Score" }
}}
])
ข้อดีของ Aggregate $max:
- รองรับ sharded collections
- เร็วกว่า (native C++ implementation)
- ใช้ memory น้อยกว่า (streaming)
- รองรับ pipeline stages อื่นๆ ได้
ขยาย: หา Max พร้อมข้อมูลอื่น (Top Document)
db.demo114.aggregate([
{ $sort: { Score: -1 } },
{ $group: {
_id: "$Name",
maxScore: { $first: "$Score" },
topDoc: { $first: "$$ROOT" }
}}
])
หลาย Metrics พร้อมกัน
db.demo114.aggregate([
{ $group: {
_id: "$Name",
maxScore: { $max: "$Score" },
minScore: { $min: "$Score" },
avgScore: { $avg: "$Score" },
count: { $sum: 1 }
}}
])
สรุป: ใช้ aggregate + $max แทน group() legacy สำหรับหาค่าสูงสุด/ต่ำสุดแยกตามกลุ่ม