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

การใช้ $project ใน MongoDB Aggregation เพื่อเลือกและแปลงฟิลด์

เลือก สร้าง และแปลงฟิลด์ด้วย $project ใน Aggregation Pipeline

Stage $project ใช้สำหรับควบคุมฟิลด์ที่จะส่งต่อไปใน Pipeline: เลือกฟิลด์ (Include/Exclude), สร้างฟิลด์ใหม่, คำนวณค่า, เปลี่ยนชื่อฟิลด์ ฯลฯ

ตัวอย่างข้อมูลทดสอบ (มีโครงสร้าง MarksInformation ต่างกัน)

> db.demo439.insertOne({ "Name": "Chris", "MarksInformation": { "Marks1": 67, "Marks2": 45, "Marks3": 78 } });
> db.demo439.insertOne({ "Name": "David", "MarksInformation": { "Marks1": 50, "Marks2": 57, "Marks3": 68 } });
> db.demo439.insertOne({ "Name": "Bob", "MarksInformation": { "Score1": 65, "Score2": 71 } });

แสดงข้อมูล

> db.demo439.find();

ผลลัพธ์: Chris, David มี Marks1-3; Bob มี Score1-2 (ไม่มี Marks3)

คำสั่ง $project แปลงให้โครงสร้างเดียวกัน (Normalize)

> db.demo439.aggregate({
  $project: {
    "Name": 1,
    "Marks1": {
      $cond: [
        { $eq: [{ $ifNull: ["$MarksInformation.Marks1", 0] }, 0] },
        { $ifNull: ["$MarksInformation.Score1", 0] },
        "$MarksInformation.Marks1"
      ]
    },
    "Marks2": {
      $cond: [
        { $eq: [{ $ifNull: ["$MarksInformation.Marks2", 0] }, 0] },
        { $ifNull: ["$MarksInformation.Score2", 0] },
        "$MarksInformation.Marks2"
      ]
    },
    "Marks3": {
      $cond: [
        { $eq: [{ $ifNull: ["$MarksInformation.Marks3", 0] }, 0] },
        { $ifNull: ["$MarksInformation.Score3", 0] },
        "$MarksInformation.Marks3"
      ]
    }
  }
});

ผลลัพธ์ที่ได้ (โครงสร้างเดียวกันทุกเอกสาร)

{ "_id": ObjectId("..."), "Name": "Chris", "Marks1": 67, "Marks2": 45, "Marks3": 78 }
{ "_id": ObjectId("..."), "Name": "David", "Marks1": 50, "Marks2": 57, "Marks3": 68 }
{ "_id": ObjectId("..."), "Name": "Bob", "Marks1": 65, "Marks2": 71, "Marks3": 0 }

คำอธิบาย Logic

  • $ifNull: ["$MarksInformation.Marks1", 0]: ถ้า Marks1 มีค่า ใช้ค่านั้น มิฉะนั้น 0
  • $eq: [..., 0]: ตรวจสอบว่าผลลัพธ์เป็น 0 หรือไม่ (หมายถึง Marks1 ไม่มี/เป็น 0)
  • $cond: [isZero, fallbackScore, originalMarks]: ถ้า Marks1 ไม่มี/เป็น 0 -> ใช้ Score1 แทน (ถ้ามี) มิฉะนั้นใช้ Marks1
  • Bob ไม่มี Marks3 และ Score3 -> ได้ 0

ฟีเจอร์ $project อื่นๆ ที่น่าสนใจ

Featureตัวอย่าง
Include/Exclude{ name: 1, _id: 0 }
Rename Field{ fullName: "$name" }
Computed Field{ total: { $add: ["$price", "$tax"] } }
Array Operations{ firstItem: { $arrayElemAt: ["$items", 0] } }
Date Operations{ year: { $year: "$date" } }

ข้อแตกต่าง $project (Aggregation) vs Projection (find)

  • find() Projection: 1/0 เท่านั้น ไม่คำนวณค่าใหม่ได้
  • $project: คำนวณ, แปลง, สร้างฟิลด์ใหม่ได้ครบครัน