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

MongoDB Aggregation: ตัด Array ภายใน Array ด้วย $slice

การ slice (ตัด) array ที่อยู่ภายใน array (nested array) ใน MongoDB ใช้ $slice ร่วมกับ $map ใน $addFields เพื่อ transform ทุก element ของ outer array

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

> db.demo111.insertOne({
  "_id" : 101,
  "Name" : "Chris",
  "Details" : [
    {
      "_id" : 101,
      "Score" : 78,
      "Subjects" : [
        { "_id" : "10001", "SubjectName" : "MySQL" },
        { "_id" : "10003", "SubjectName" : "MongoDB" }
      ]
    },
    {
      "_id" : 102,
      "Score" : 87,
      "Subjects" : [
        { "_id" : "10004", "SubjectName" : "Java" }
      ]
    }
  ]
});
{ "acknowledged" : true, "insertedId" : 101 }

แสดงข้อมูล

> db.demo111.find();

ผลลัพธ์: Details array 2 elements, แต่ละ element มี Subjects array

Query Slice Subjects Array ให้เหลือ 1 Element แรก

> db.demo111.aggregate([
  { "$addFields": {
    "Details": {
      "$map": {
        "input": "$Details",
        "as": "out",
        "in": {
          "_id": "$$out._id",
          "Score": "$$out.Score",
          "Subjects": { "$slice": ["$$out.Subjects", 1] }
        }
      }
    }
  }}
])

คำอธิบาย:

  1. $addFields: แทนที่ Details array ด้วยผลลัพธ์ใหม่ คง field อื่นๆ
  2. $map: วนลูปแต่ละ element ใน Details (ตัวแปร $$out)
  3. $slice: ["$$out.Subjects", 1]: ตัด array Subjects ให้เหลือ 1 element แรก (index 0)
  4. สร้าง object ใหม่รวม _id, Score, และ Subjects ที่ slice แล้ว

ผลลัพธ์

{ "_id" : 101, "Name" : "Chris", "Details" : [
  { "_id" : 101, "Score" : 78, "Subjects" : [ { "_id" : "10001", "SubjectName" : "MySQL" } ] },
  { "_id" : 102, "Score" : 87, "Subjects" : [ { "_id" : "10004", "SubjectName" : "Java" } ] }
] }

Subjects ของแต่ละ element เหลือแค่ตัวแรก (MySQL, Java)

$slice Syntax

{ $slice: [ ,  ] }           // n elements แรก
{ $slice: [ , ,  ] }   // ข้าม skip ตัว แล้วเอา n ตัว

ตัวอย่าง $slice แบบ Skip + Limit

// ข้าม 1 ตัว แล้วเอา 2 ตัว (element ที่ 2-3)
{ $slice: ["$$out.Subjects", 1, 2] }

ใช้ $slice ใน $project (Top-level Array)

db.demo111.aggregate([
  { $project: {
    Name: 1,
    firstSubject: { $slice: ["$Details.Subjects", 1] }  // ไม่ได้ - Details.Subjects เป็น array of arrays
  }}
])

ต้อง $unwind ก่อน หรือใช้ $map เหมือนตัวอย่างหลัก

Slice หลัง $unwind (วิธีอื่น)

db.demo111.aggregate([
  { $unwind: "$Details" },
  { $project: {
    _id: 1, Name: 1,
    "Details._id": 1, "Details.Score": 1,
    "Details.Subjects": { $slice: ["$Details.Subjects", 1] }
  }}
])

สรุป: $map + $slice = วิธีมาตรฐานสำหรับ slice nested arrays ทุก element พร้อมกัน

nผลลัพธ์
1Element แรก 1 ตัว
3Element แรก 3 ตัว
-1Element สุดท้าย 1 ตัว
-2Element สุดท้าย 2 ตัว