การ filter array elements ใน MongoDB aggregate โดยเก็บ field อื่นๆ ไว้เหมือนเดิม ใช้ $addFields ร่วมกับ $filter แทน $project ที่ต้องระบุทุก field
สร้างคอลเลกชันและข้อมูลตัวอย่าง
> db.demo118.insertOne({
"Id" : "101",
"Name" : "Chris",
"Subjects" : ["MySQL", "MongoDB", "Java"],
"Details" : [
{ "Name" : "David", "S": "MongoDB" },
{ "Name" : "Bob", "S": "Python" }
]
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2f0c0cd8f64a552dae6364") }
แสดงข้อมูล
> db.demo118.find();
ผลลัพธ์: มี Subjects array และ Details array (มี field S)
Query Filter Details ให้เหลือเฉพาะที่ S อยู่ใน Subjects
> db.demo118.aggregate([
{
"$addFields": {
"Details": {
"$filter": {
"input": "$Details",
"as": "out",
"cond": { "$in": ["$$out.S", "$Subjects"] }
}
}
}
}
]).pretty();
คำอธิบาย:
$addFields: แทนที่ field Details เดิมด้วยผลลัพธ์ที่ filter แล้ว คง field อื่นๆ ไว้ทั้งหมด (ต่างจาก $project)$filter: วนลูป input array ($Details) ตัวแปร $$out$in: ["$$out.S", "$Subjects"]: ตรวจสอบว่า field S ของ element อยู่ใน array Subjects หรือไม่
ผลลัพธ์
{ "_id" : ObjectId("5e2f0c0cd8f64a552dae6364"), "Id" : "101", "Name" : "Chris",
"Subjects" : [ "MySQL", "MongoDB", "Java" ],
"Details" : [ { "Name" : "David", "S" : "MongoDB" } ] }
เหลือเฉพาะ David (S="MongoDB" อยู่ใน Subjects) Bob ถูก filter ออก (S="Python" ไม่อยู่ใน Subjects)
เปรียบเทียบ $addFields vs $project
| Feature | $addFields | $project |
|---|---|---|
| คง field เดิม | ✓ อัตโนมัติ | ✗ ต้องระบุทุก field |
| เพิ่ม field ใหม่ | ✓ | ✓ |
| ลบ field | ✗ (ต้อง $project ต่อ) | ✓ (0: false) |
| Rename field | ✗ | ✓ |