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

Lấy danh sách giá trị bằng MongoDB $group và $push

Để nhóm tài liệu theo một trường và gom các giá trị của trường khác thành mảng, MongoDB sử dụng stage $group kết hợp với toán tử accumulator $push trong Aggregation Framework.

Tạo dữ liệu mẫu

> db.groupByDemo.insertOne({"UserName":"John","Subject":"MongoDB"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd69f0457806ebf1256f136") }
> db.groupByDemo.insertOne({"UserName":"Larry","Subject":"MySQL"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd69f0657806ebf1256f137") }
> db.groupByDemo.insertOne({"UserName":"John","Subject":"Java"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd69f0d57806ebf1256f138") }
> db.groupByDemo.insertOne({"UserName":"John","Subject":"C"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd69f1357806ebf1256f139") }
> db.groupByDemo.insertOne({"UserName":"Larry","Subject":"SQL Server"});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd69f1c57806ebf1256f13a") }

Xem dữ liệu

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

Nhóm theo UserName và gom Subject thành mảng

> db.groupByDemo.aggregate({$group: { '_id': '$UserName', 'Subject': { $push: '$Subject' }}});

Kết quả


Giải thích

  • _id: '$UserName': Khóa nhóm (group key) - nhóm theo trường UserName
  • $push: '$Subject': Đẩy giá trị Subject của mỗi tài liệu vào mảng kết quả
  • Thứ tự trong mảng tuân theo thứ tự tài liệu xuất hiện trong collection (không đảm bảo sort)

Các biến thể hữu ích

1. $addToSet - Loại bỏ trùng lặp

db.groupByDemo.aggregate({$group: {_id: '$UserName', Subject: {$addToSet: '$Subject'}}});

2. Sắp xếp trong mảng kết quả

db.groupByDemo.aggregate([
  {$sort: {Subject: 1}},  // Sort trước khi push
  {$group: {_id: '$UserName', Subject: {$push: '$Subject'}}}
]);

3. Thêm nhiều trường vào kết quả

db.groupByDemo.aggregate([
  {$group: {
    _id: '$UserName', 
    Subjects: {$push: '$Subject'}, 
    Count: {$sum: 1},
    FirstSubject: {$first: '$Subject'},
    LastSubject: {$last: '$Subject'}
  }}
]);

4. Giữ lại _id gốc của tài liệu

db.groupByDemo.aggregate([
  {$group: {_id: '$UserName', Docs: {$push: '$$ROOT'}}}
]);

Lưu ý hiệu năng

  • Tạo index trên trường group key: db.groupByDemo.createIndex({UserName: 1})
  • $push có giới hạn 16MB cho document kết quả (BSON limit)
  • Với dữ liệu lớn, cân nhắc allowDiskUse: true