Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MongoDB

Tổng điểm theo nhóm nhiều cột (id, Name) với ID trùng lặp trong MongoDB

Sử dụng aggregate() với hai stage $group để tính tổng điểm nhóm theo cả id và Name, xử lý trường hợp ID trùng nhưng Name khác nhau.

Tạo collection dữ liệu điểm

> db.demo627.insertOne({id:101, "Name":"Chris", "Marks":54});
> db.demo627.insertOne({id:102, "Name":"Bob", "Marks":74});
> db.demo627.insertOne({id:101, "Name":"Chris", "Marks":87});
> db.demo627.insertOne({id:102, "Name":"Mike", "Marks":70});

Hiển thị dữ liệu gốc

> db.demo627.find();

Kết quả (4 document, id 101 và 102 mỗi cái 2 document):

id:101 Chris 54 | id:102 Bob 74 | id:101 Chris 87 | id:102 Mike 70

Pipeline aggregate 2 cấp $group

> db.demo627.aggregate([
  {
    "$group": {
      "_id": { "id": "$id", "Name": "$Name" },
      "Marks": { "$sum": "$Marks" }
    }
  },
  {
    "$group": {
      "_id": { "id": "$_id.id", "Name": "$_id.Name" },
      "TotalMarks": { "$sum": "$Marks" }
    }
  }
], { "allowDiskUse": true });

Kết quả:

{
  "_id" : { "id" : 101, "Name" : "Chris" }, "TotalMarks" : 141
}
{
  "_id" : { "id" : 102, "Name" : "Bob" }, "TotalMarks" : 74
}
{
  "_id" : { "id" : 102, "Name" : "Mike" }, "TotalMarks" : 70
}

Giải thích:

  1. $group đầu tiên: Gom theo cặp (id, Name) → tính tổng Marks cho mỗi cặp. Kết quả trung gian: (101,Chris)=141, (102,Bob)=74, (102,Mike)=70
  2. $group thứ hai: Gom lại theo (id, Name) từ kết quả trung gian → tổng Marks (trong trường hợp này mỗi cặp chỉ có 1 record trung gian nên kết quả không đổi)

Tại sao cần 2 $group? Pattern này dùng khi cần tổng hợp đa cấp, ví dụ: trước gom theo (id, Name, Subject), sau gom theo (id, Name) để tính tổng tất cả môn. Ví dụ này đơn giản hóa để demo cú pháp.

allowDiskUse: true cho phép dùng disk tạm khi dữ liệu lớn vượt giới hạn bộ nhớ (100MB).