MongoDB không có toán tử xóa trực tiếp theo chỉ số (index) của mảng. Cách phổ biến: dùng $unset đặt phần tử thành null theo vị trí, sau đó $pull loại bỏ các null.
Cú pháp (2 bước)
// Bước 1: Unset phần tử tại index N (0-based)
db.collection.update({}, { $unset: { "tênMảng.N": 1 } });
// Bước 2: Pull các null còn sót lại
db.collection.update({}, { $pull: { "tênMảng": null } });
Ví dụ minh họa
Tạo collection getNThElementDemo:
> db.getNThElementDemo.insertOne({ "UserName": "John", "UserAge": 23, "ListOfFriends": ["Carol", "Sam", "Mike", "Bob"] });
> db.getNThElementDemo.insertOne({ "UserName": "David", "UserAge": 21, "ListOfFriends": ["Chris", "Robert"] });
Hiển thị (ListOfFriends của John: index 0=Carol, 1=Sam, 2=Mike, 3=Bob):
> db.getNThElementDemo.find().pretty();
Kết quả:
{ "_id" : ..., "UserName" : "John", "UserAge" : 23, "ListOfFriends" : [ "Carol", "Sam", "Mike", "Bob" ] }
{ "_id" : ..., "UserName" : "David", "UserAge" : 21, "ListOfFriends" : [ "Chris", "Robert" ] }
Xóa phần tử index 2 (Mike) của John
> db.getNThElementDemo.update({}, { $unset: { "ListOfFriends.2": 1 } });
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.getNThElementDemo.update({}, { $pull: { "ListOfFriends": null } });
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Lưu ý: update({}, ...) không có filter sẽ cập nhật **document đầu tiên** khớp (thường là John). Trong production, hãy thêm filter cụ thể (ví dụ: { UserName: "John" }).
Kiểm tra kết quả:
> db.getNThElementDemo.find().pretty();
Kết quả:
{ "_id" : ..., "UserName" : "John", "UserAge" : 23, "ListOfFriends" : [ "Carol", "Sam", "Bob" ] }
{ "_id" : ..., "UserName" : "David", "UserAge" : 21, "ListOfFriends" : [ "Chris", "Robert" ] }
Phần tử "Mike" (index 2) đã bị xóa, mảng tự co lại.
Cách khác: Aggregation Pipeline Update (MongoDB 4.2+)
db.getNThElementDemo.updateOne(
{ UserName: "John" },
[{ $set: { ListOfFriends: { $concatArrays: [ { $slice: ["$ListOfFriends", 2] }, { $slice: ["$ListOfFriends", 3, { $size: "$ListOfFriends" }] } ] } } }]
);
Cách này phức tạp hơn nhưng atomic (single operation).
Lưu ý quan trọng
- Index mảng **0-based** (phần tử đầu = 0).
- Nếu index vượt quá độ dài mảng,
$unsetkhông báo lỗi nhưng cũng không làm gì. $pull: { arr: null }sẽ xóa **TẤT CẢ** null trong mảng (cẩn thận nếu mảng có null hợp lệ).- Để xóa theo giá trị (không theo vị trí):
$pull: { ListOfFriends: "Mike" }.