เพื่อกรองและดึงเฉพาะฟิลด์ที่ต้องการจากออบเจกต์ในอาร์เรย์ ให้ใช้ $project ร่วมกับ $filter และ $match ใน Aggregation Pipeline
> db.demo507.insertOne({
... "Information": [
... {"Name": "John", "SubjectName": "MySQL"},
... {"Name": "Bob", "SubjectName": "MongoDB"},
... {"Name": "Chris", "SubjectName": "MySQL"},
... {"Name": "David", "SubjectName": "C++"}
... ]
... });
{ "acknowledged" : true, "insertedId" : ObjectId("5e8836d3987b6e0e9d18f577") }
แสดงข้อมูล:
> db.demo507.find().pretty();
{ "_id" : ObjectId("5e8836d3987b6e0e9d18f577"), "Information" : [ { "Name" : "John", "SubjectName" : "MySQL" }, { "Name" : "Bob", "SubjectName" : "MongoDB" }, { "Name" : "Chris", "SubjectName" : "MySQL" }, { "Name" : "David", "SubjectName" : "C++" } ] }
คิวรีกรองเฉพาะ SubjectName = "MySQL"
> db.demo507.aggregate([
... {$match: {"Information.SubjectName": "MySQL"}},
... {$project: {
... _id: 0,
... Information: {
... $filter: {
... input: '$Information',
... as: 'result',
... cond: {$eq: ['$$result.SubjectName', 'MySQL']}
... }
... }
... }},
... {$project: {Information: {SubjectName: 1}}}
... ]);
ผลลัพธ์ - ได้เฉพาะ SubjectName ที่เป็น MySQL:
{ "Information" : [ { "SubjectName" : "MySQL" }, { "SubjectName" : "MySQL" } ] }
คำอธิบายขั้นตอน
- $match: กรองเอกสารที่มี SubjectName = "MySQL" อย่างน้อย 1 รายการ
- $project + $filter: ในอาร์เรย์ Information เก็บเฉพาะออบเจกต์ที่ SubjectName = "MySQL"
- $project (ครั้งที่ 2): แสดงเฉพาะฟิลด์ SubjectName ซ่อน Name ออกไป
เทคนิคนี้เหมาะสำหรับการดึงข้อมูลย่อย (sub-documents) ที่ตรงเงื่อนไข โดยไม่ต้องดึงเอกสารทั้งหมดมาประมวลผลที่แอปพลิเคชัน