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

MongoDB: ดึงฟิลด์เฉพาะจาก nested array documents ด้วย $filter และ $project

ใช้ $filter ร่วม $project ใน aggregation pipeline เพื่อดึงเฉพาะฟิลด์ที่ต้องการจาก nested array documents สร้างคอลเลกชันตัวอย่าง (nested 3 ระดับ):

> db.demo342.insertOne({
  "Id": "101",
  "details1" : {
    "details2" : [
      {
        "details3" : [
          { "Name": "Mike", "CountryName" : "US" },
          { "Name": "David", "CountryName" : "AUS" },
          { "Name": "Bob", "CountryName" : "UK" }
        ]
      }
    ]
  }
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e53ef99f8647eb59e5620a9") }

แสดงข้อมูล:

> db.demo342.find();

คิวรี aggregation ดึงเฉพาะรายการที่ Name = "Bob" ในระดับลึกที่สุด:

> db.demo342.aggregate([
  { "$project": {
    "details1": {
      "details2": {
        "$filter": {
          "input": {
            "$map": {
              "input": "$details1.details2",
              "in": {
                "details3": {
                  "$filter": {
                    "input": "$$this.details3",
                    "cond": { "$eq": ["$$this.Name", "Bob"] }
                  }
                }
              }
            }
          },
          "cond": { "$ne": ["$$this.details3", []] }
        }
      }
    }
  }}
])

ผลลัพธ์ (ได้เฉพาะ Bob):

{ "_id" : ObjectId("5e53ef99f8647eb59e5620a9"), "details1" : { "details2" : [ { "details3" : [ { "Name" : "Bob", "CountryName" : "UK" } ] } ] } }

คำอธิบาย Pipeline

  • $map: วนลูปผ่าน details2 สร้างโครงสร้างใหม่
  • $filter (ภายใน): กรอง details3 ให้เหลือเฉพาะ Name = "Bob"
  • $filter (ภายนอก): กรอง details2 ให้เหลือเฉพาะที่ details3 ไม่ใช่ array ว่าง
  • $$this อ้างอิงสมาชิกปัจจุบันใน $map/$filter

หมายเหตุ

MongoDB 4.4+ มี $reduce และ $function ที่อาจทำให้ query สั้นลง สำหรับ nested array หลายระดับ ควรพิจารณา schema design ใหม่ให้ flat กว่านี้เพื่อ query ง่ายขึ้น