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

ดึงหลายรายการใน Array MongoDB ด้วย Aggregation ($unwind, $match, $group)

ใช้ Aggregation Pipeline: $unwind แยก Array → $match กรอง → $group รวมกลับ → $project จัดรูปแบบ เพื่อดึงหลายรายการที่ตรงเงื่อนไขจาก Array of Objects

สร้างคอลเลกชันและข้อมูลตัวอย่าง

> db.retrieveMultipleDemo.insertOne({
    "UserDetails": [
      {"_id": "101", "UserName": "John", "UserAge": 23},
      {"_id": "102", "UserName": "Carol", "UserAge": 21},
      {"_id": "103", "UserName": "David", "UserAge": 23},
      {"_id": "104", "UserName": "Sam", "UserAge": 25}
    ]
  });
{ "acknowledged": true, "insertedId": ObjectId("5cd40c85edc6604c74817cf0") }

แสดงข้อมูล

> db.retrieveMultipleDemo.find().pretty();

ผลลัพธ์: 1 เอกสาร มี Array UserDetails 4 Elements

Aggregation: ดึง User ที่ Age = 23 และ _id ใน [101, 103]

> db.retrieveMultipleDemo.aggregate([
  {$unwind: "$UserDetails"},
  {$match: {"UserDetails._id": {$in: ["101", "103"]}, "UserDetails.UserAge": 23}},
  {$group: {"_id": "$_id", "UserDetails": {$push: "$UserDetails"}}},
  {$project: {"_id": 0, "UserDetails": 1}}
]);

ผลลัพธ์: ได้ John และ David (Age 23, ID ในรายการ)

{
  "UserDetails": [
    {"_id": "101", "UserName": "John", "UserAge": 23},
    {"_id": "103", "UserName": "David", "UserAge": 23}
  ]
}

ขั้นตอน Pipeline

  1. $unwind: แยก Array UserDetails → 4 Documents (แต่ละ Document มี 1 UserDetail)
  2. $match: กรองเฉพาะที่ _id ใน ["101","103"] และ UserAge = 23
  3. $group: รวมกลับตาม _id ของ Document ต้นทาง ($push สร้าง Array ใหม่)
  4. $project: จัดรูปแบบ Output (ซ่อน _id, แสดง UserDetails)

ตัวแปร myIds ในตัวอย่างต้นฉบับ

โค้ดต้นฉบับใช้ myIds ซึ่งควรเป็น Array Variable ใน Shell:

var myIds = ["101", "103"];
db.retrieveMultipleDemo.aggregate([
  {$unwind: "$UserDetails"},
  {$match: {"UserDetails._id": {$in: myIds}, "UserDetails.UserAge": 23}},
  {$group: {"_id": "$_id", "UserDetails": {$push: "$UserDetails"}}},
  {$project: {"_id": 0, "UserDetails": 1}}
]);

เทคนิคเพิ่มเติม

  • $replaceRoot แทน $group + $project (MongoDB 3.6+):
    {$replaceRoot: {newRoot: "$UserDetails"}}
  • $elemMatch ใน find() สำหรับกรณีง่าย (คืน Element เดียว):
    db.coll.find({}, {"UserDetails": {$elemMatch: {UserAge: 23}}})
  • Performance: $unwind เพิ่ม Document Count → ใช้ $match ก่อน $unwind ถ้าเป็นไปได้ (แต่ Match ต้องอยู่ใน Array จึงต้อง Unwind ก่อน)