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

เรียงลำดับ MongoDB ตาม Subdocument Match ด้วย Aggregation

บทความนี้สาธิตการใช้ Aggregation Framework เพื่อกรอง (Filter) และ เรียงลำดับ (Sort) เอกสารตามค่าใน Subdocument (Object ใน Array) โดยเฉพาะกรองเฉพาะ Subdocument ที่ Age = 21 แล้วเรียงตาม StudentScore

สร้างข้อมูลตัวอย่าง

> 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") }

แสดงข้อมูลต้นฉบับ

> db.sortBySubDocumentsDemo.find().pretty();
{
  "_id" : ObjectId("5cd57e297924bb85b3f48942"),
  "StudentName" : "Chris",
  "StudentDetails" : [
    { "Age" : 21, "StudentScore" : 91 },
    { "Age" : 22, "StudentScore" : 99 },
    { "Age" : 21, "StudentScore" : 93 }
  ]
}
{
  "_id" : ObjectId("5cd57e4c7924bb85b3f48943"),
  "StudentName" : "Robert",
  "StudentDetails" : [
    { "Age" : 24, "StudentScore" : 78 },
    { "Age" : 21, "StudentScore" : 86 },
    { "Age" : 23, "StudentScore" : 45 }
  ]
}

Aggregation Pipeline: กรอง Age=21 แล้วเรียงตาม Score

> 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 }
]);

ผลลัพธ์

{ "StudentName" : "Robert", "StudentDetails" : { "StudentScore" : 86 } }
{ "StudentName" : "Chris", "StudentDetails" : { "StudentScore" : 91 } }
{ "StudentName" : "Chris", "StudentDetails" : { "StudentScore" : 93 } }

คำอธิบายแต่ละ Stage

  1. $match (Stage 1): กรอง Document 级别 - เก็บเอกสารที่มี อย่างน้อย 1 Subdocument ที่ Age=21
  2. $unwind: แยก Array StudentDetails ให้แต่ละ Subdocument กลายเป็น Document แยกต่างหาก
  3. $match (Stage 2): กรอง Subdocument 级别 - เก็บเฉพาะที่ Age=21 จริงๆ
  4. $project: เลือกฟิลด์ที่ต้องการ (StudentName, StudentScore) ซ่อน _id
  5. $sort: เรียงจาก Score น้อยไปมาก (1 = Ascending)
  6. $limit: จำกัดผลลัพธ์ 5 รายการ

จุดสำคัญ

ต้องใช้ $unwind ก่อนจึงจะ Filter/ Sort ได้ที่ระดับ Subdocument จริง มิฉะนั้น $match แรกจะ Filter ที่ระดับ Document (มี Subdocument ใด Subdocument หนึ่งตรงก็ผ่าน)