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

Sắp xếp theo khớp tài liệu con trong MongoDB

Để sắp xếp tài liệu dựa trên giá trị trong mảng các tài liệu con (subdocuments), MongoDB sử dụng Aggregation Pipeline với các stage: $match, $unwind, $project, $sort, $limit.

Tạo dữ liệu mẫu

> db.sortBySubDocumentsDemo.insertOne( 
  { 
    "StudentName": "Chris", 
    "StudentDetails": [ 
      { "Age":21, "StudentScore":91 }, 
      { "Age":22, "StudentScore":99 }, 
      { "Age":21, "StudentScore":93 } 
    ] 
  } 
);
{ "acknowledged" : true, "insertedId" : ObjectId("5cd57e297924bb85b3f48942") }

> db.sortBySubDocumentsDemo.insertOne( 
  { 
    "StudentName": "Robert", 
    "StudentDetails": [ 
      { "Age":24, "StudentScore":78 }, 
      { "Age":21, "StudentScore":86 }, 
      { "Age":23, "StudentScore":45 } 
    ] 
  } 
);
{ "acknowledged" : true, "insertedId" : ObjectId("5cd57e4c7924bb85b3f48943") }

Xem dữ liệu

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

Sắp xếp theo StudentScore của subdocument có Age = 21

> db.sortBySubDocumentsDemo.aggregate([ 
  {$match: {'StudentDetails.Age': 21 }}, 
  {$unwind: '$StudentDetails'}, 
  {$match: {'StudentDetails.Age': 21}}, 
  {$project: {_id: 0, "StudentName": 1, 'StudentDetails.StudentScore': 1}}, 
  {$sort: { 'StudentDetails.StudentScore': 1 }}, 
  {$limit: 5} 
]);

Kết quả


Giải thích từng stage

  1. $match (1): Lọc trước tài liệu cha có ít nhất một subdocument Age=21 (giảm dữ liệu xử lý)
  2. $unwind: "Phẳng hóa" mảng StudentDetails → mỗi subdocument thành một tài liệu riêng
  3. $match (2): Lọc tiếp chỉ giữ subdocument có Age=21
  4. $project: Chọn trường cần thiết, loại _id, giữ StudentName và StudentScore
  5. $sort: Sắp xếp tăng dần theo StudentScore (1 = asc, -1 = desc)
  6. $limit: Giới hạn 5 kết quả

Tại sao cần 2 $match?

  • Match đầu: Lọc ở mức tài liệu cha (hiệu quả hơn, giảm dữ liệu vào $unwind)
  • Match sau: Lọc ở mức subdocument sau khi đã unwind

Mở rộng: Giữ cấu trúc mảng gốc

Nếu muốn giữ mảng và chỉ sắp xếp tài liệu cha theo max/min score của subdocument Age=21:

db.sortBySubDocumentsDemo.aggregate([
  {$match: {'StudentDetails.Age': 21}},
  {$addFields: {
    minScoreAge21: {$min: "$StudentDetails.StudentScore"},
    maxScoreAge21: {$max: "$StudentDetails.StudentScore"}
  }},
  {$sort: {minScoreAge21: 1}}
]);