Cập nhật phần tử mảng chính xác với Positional $ Operator
Toán tử positional $ xác định vị trí phần tử khớp trong mảng để cập nhật chính xác phần tử đó.
1. Dữ liệu: mảng DueDateDetails
> db.demo462.insertOne({
id: 1,
DueDateDetails: [
{ Name: "David", Age: 21, CountryName: ["US", "UK"] },
{ Name: "Chris", Age: 23, CountryName: ["UK"] }
]
});
{ "acknowledged": true, "insertedId": ObjectId("5e7f6c59cb66ccba22cc9dce") }
2. Cập nhật CountryName của Chris thành "AUS"
> db.demo462.updateOne(
{ id: 1, "DueDateDetails.Name": "Chris" },
{ $set: { "DueDateDetails.$.CountryName": "AUS" } }
);
{ "acknowledged": true, "matchedCount": 1, "modifiedCount": 1 }
3. Kết quả
> db.demo462.find().pretty();
{
"_id": ObjectId("5e7f6c59cb66ccba22cc9dce"),
"id": 1,
"DueDateDetails": [
{ "Name": "David", "Age": 21, "CountryName": ["US", "UK"] },
{ "Name": "Chris", "Age": 23, "CountryName": "AUS" } // Đã thay đổi từ ["UK"] → "AUS"
]
}
Cơ chế Positional $ Operator
- Filter
"DueDateDetails.Name": "Chris"tìm thấy phần tử index 1 $trong update tham chiếu đến chính phần tử index 1 đó- Chỉ cập nhật phần tử khớp, không ảnh hưởng phần tử khác
Các biến thể Positional Operator (MongoDB 3.6+)
| Operator | Tên | Áp dụng cho |
|---|---|---|
| Positional (first match) | Phần tử ĐẦU TIÊN khớp filter | |
| All positional | TẤT CẢ phần tử trong mảng | |
| Filtered positional | Phần tử khớp arrayFilters |
Ví dụ $[] (cập nhật tất cả phần tử)
// Thêm "VN" vào CountryName của TẤT CẢ học sinh
db.demo462.updateOne(
{ id: 1 },
{ $push: { "DueDateDetails.$[].CountryName": "VN" } }
);
Ví dụ $[] (filtered positional)
// Chỉ cập nhật học sinh Age > 22
db.demo462.updateOne(
{ id: 1 },
{ $set: { "DueDateDetails.$[elem].Status": "Senior" } },
{ arrayFilters: [{ "elem.Age": { $gt: 22 } }] }
);
Lưu ý quan trọng
- Positional
$chỉ hoạt động khi filter mảng ở cấp độ 1 - Mảng lồng nhiều cấp (nested array) → dùng
$[với] arrayFilters - Filter trong updateOne phải khớp document VÀ phần tử mảng