การใช้ $slice Operator เพื่อดึง Element สุดท้ายของ Array ใน MongoDB
ใช้ $slice ใน Projection ของ find() ด้วยค่าติดลบ เพื่อดึง Element จากท้าย Array กลับมา
ไวยากรณ์
db.yourCollectionName.find({}, {yourArrayFieldName: {$slice: -1}});
ตัวอย่างการสร้างคอลเลกชันและเพิ่มข้อมูล
> db.getLastElementOfArrayDemo.insertOne({"StudentName":"James","StudentMathScore":[78,68,98]});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9d2d71a629b87623db1b2e") }
> db.getLastElementOfArrayDemo.insertOne({"StudentName":"Chris","StudentMathScore":[88,56,34]});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9d2d83a629b87623db1b2f") }
> db.getLastElementOfArrayDemo.insertOne({"StudentName":"Larry","StudentMathScore":[99]});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9d2d8ea629b87623db1b30") }
> db.getLastElementOfArrayDemo.insertOne({"StudentName":"Robert","StudentMathScore":[90,78,67,66,75,73]});
{ "acknowledged" : true, "insertedId" : ObjectId("5c9d2dada629b87623db1b31") }
แสดงข้อมูลทั้งหมด
> db.getLastElementOfArrayDemo.find().pretty();
ผลลัพธ์:
{ "_id" : ObjectId("5c9d2d71a629b87623db1b2e"), "StudentName" : "James", "StudentMathScore" : [ 78, 68, 98 ] }
{ "_id" : ObjectId("5c9d2d83a629b87623db1b2f"), "StudentName" : "Chris", "StudentMathScore" : [ 88, 56, 34 ] }
{ "_id" : ObjectId("5c9d2d8ea629b87623db1b30"), "StudentName" : "Larry", "StudentMathScore" : [ 99 ] }
{ "_id" : ObjectId("5c9d2dada629b87623db1b31"), "StudentName" : "Robert", "StudentMathScore" : [ 90, 78, 67, 66, 75, 73 ] }
ดึง Element สุดท้ายของ Array (StudentMathScore)
> db.getLastElementOfArrayDemo.find({}, {StudentMathScore: {$slice: -1}});
ผลลัพธ์ (เฉพาะ Element สุดท้าย):
{ "_id" : ObjectId("5c9d2d71a629b87623db1b2e"), "StudentName" : "James", "StudentMathScore" : [ 98 ] }
{ "_id" : ObjectId("5c9d2d83a629b87623db1b2f"), "StudentName" : "Chris", "StudentMathScore" : [ 34 ] }
{ "_id" : ObjectId("5c9d2d8ea629b87623db1b30"), "StudentName" : "Larry", "StudentMathScore" : [ 99 ] }
{ "_id" : ObjectId("5c9d2dada629b87623db1b31"), "StudentName" : "Robert", "StudentMathScore" : [ 73 ] }
คำอธิบาย $slice Values
| ค่า $slice | ความหมาย | ตัวอย่าง Array [1,2,3,4,5] |
|---|---|---|
| 3 | 3 Element แรก (จากหน้า) | [1, 2, 3] |
| -3 | 3 Element สุดท้าย (จากท้าย) | [3, 4, 5] |
| [2, 3] | Skip 2, Limit 3 (จากหน้า) | [3, 4, 5] |
| [-3, 2] | Skip 3 จากท้าย, Limit 2 | [3, 4] |
ตัวอย่าง $slice เพิ่มเติม
// 3 Element แรก
db.collection.find({}, { scores: { $slice: 3 } });
// 3 Element สุดท้าย
db.collection.find({}, { scores: { $slice: -3 } });
// Skip 2, Take 3 (Pagination ใน Array)
db.collection.find({}, { scores: { $slice: [2, 3] } });
// กรณี Array ว่างหรือไม่มี Field -> คืน [] หรือ Missing
การใช้ $slice ใน Aggregation (MongoDB 3.2+)
db.collection.aggregate([
{ $project: {
lastScore: { $arrayElemAt: ["$scores", -1] }, // ค่า Scalar โดยตรง
lastThree: { $slice: ["$scores", -3] } // Array 3 ตัวท้าย
}}
]);
ความแตกต่าง:
- find() + $slice: คืน Array (แม้ 1 Element ก็เป็น Array)
- $arrayElemAt: คืน Scalar Value โดยตรง
- aggregation $slice: คืน Array
กรณี Array ว่างหรือ Missing Field
> db.demo.insertOne({ name: "Empty", scores: [] });
> db.demo.insertOne({ name: "Missing" }); // ไม่มี scores field
> db.demo.find({}, { scores: { $slice: -1 } });
{ "name": "Empty", "scores": [] }
{ "name": "Missing" } // ไม่มี scores field ในผลลัพธ์
Best Practices
- ใช้ $slice: -1 ใน find() สำหรับกรณีง่าย ต้องการ Array กลับมา
- ใช้ $arrayElemAt: ["$field", -1] ใน Aggregation ต้องการ Scalar Value
- รวมกับ Projection ฟิลด์อื่นๆ เพื่อลด Bandwidth
- Index ไช่วย $slice ได้ (ต้อง Scan Document)