Phương thức save(): Upsert tự động (insert hoặc update)
db.collection.save(doc) tự động quyết định: nếu doc có _id → update (replace), nếu không có _id → insert mới.
1. Ví dụ: Insert 4 document (không có _id)
> db.demo481.save({ "FirstName": "Chris", "LastName": "Brown" });
WriteResult({ "nInserted": 1 })
> db.demo481.save({ "FirstName": "David", "LastName": "Miller" });
WriteResult({ "nInserted": 1 })
> db.demo481.save({ "FirstName": "John", "LastName": "Doe" });
WriteResult({ "nInserted": 1 })
> db.demo481.save({ "FirstName": "John", "LastName": "Smith" });
WriteResult({ "nInserted": 1 })
2. Kết quả: 4 document với _id tự động
> db.demo481.find();
{ "_id": ObjectId("5e82db39b0f3fa88e227909c"), "FirstName": "Chris", "LastName": "Brown" }
{ "_id": ObjectId("5e82db45b0f3fa88e227909d"), "FirstName": "David", "LastName": "Miller" }
{ "_id": ObjectId("5e82db4db0f3fa88e227909e"), "FirstName": "John", "LastName": "Doe" }
{ "_id": ObjectId("5e82db52b0f3fa88e227909f"), "FirstName": "John", "LastName": "Smith" }
3. Cập nhật: Gọi save() với _id đã có
> var doc = db.demo481.findOne({ FirstName: "Chris" });
> doc.LastName = "White";
> db.demo481.save(doc);
WriteResult({ "nMatched": 1, "nUpserted": 0, "nModified": 1 })
⚠️ save() ĐÃ DEPRECATED (MongoDB 4.2+)
| Phương thức cũ | Thay thế hiện đại | Lưu ý |
|---|---|---|
| save(doc) | insertOne(doc) / replaceOne({_id}, doc) | Tách biệt rõ ràng insert vs replace |
| update() | updateOne() / updateMany() | Rõ ràng số lượng doc ảnh hưởng |
| remove() | deleteOne() / deleteMany() | Rõ ràng số lượng doc xóa |
Tại sao save() không khuyến khích?
- Nhầm lẫn giữa insert và replace (gây bug: vô tình tạo doc mới khi _id sai)
replaceOnethay thế TOÀN BỘ doc (kể cả trường không gửi) → mất data nếu không cẩn thận- Không hỗ trợ atomic operators (
$set,$inc,$push...) - Không trả về chi tiết kết quả như write concern
Best Practice hiện nay
// INSERT mới (tự động gen _id)
db.collection.insertOne({ name: "New" });
// UPDATE một phần (an toàn, giữ trường khác)
db.collection.updateOne(
{ _id: existingId },
{ $set: { name: "Updated" } }
);
// REPLACE toàn bộ (nếu thực sự muốn)
db.collection.replaceOne(
{ _id: existingId },
{ name: "New Name", otherField: "value" }
);
Tóm lại: Chỉ dùng save() trong shell ad-hoc, KHÔNG dùng trong production code.