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

MongoDB: หาคะแนนสูงสุด (Max Score) ของชื่อซ้ำด้วย group()

การหาค่าสูงสุด (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}: จัดกลุ่มตาม Name
  • initial: ค่าเริ่มต้นของ 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 สำหรับหาค่าสูงสุด/ต่ำสุดแยกตามกลุ่ม