เมื่อใช้ Custom _id (กำหนด _id เอง) การ insert() จะ error ถ้า _id ซ้ำ ต้องใช้ update() พร้อม upsert: true แทน
ปัญหาของ insert() กับ Custom _id
> db.customIdDemo.insert({ "_id": 1, "StudentName": "John" });
WriteResult({ "nInserted" : 1 })
> db.customIdDemo.insert({ "_id": 1, "StudentName": "Carol" });
// Error: E11000 duplicate key error collection: ... _id_ dup key: { : 1.0 }
วิธีแก้: ใช้ update() + upsert: true
db.collection.update(
{ _id: customId },
{ $set: { "field": "value" } },
{ upsert: true }
);
ตัวอย่าง: Custom _id แบบตัวเลข
1. Insert ครั้งแรก (สำเร็จ)
> db.customIdDemo.insert({ "_id": 1, "StudentName": "John" });
WriteResult({ "nInserted" : 1 })
2. Insert ซ้ำ _id = 1 (Error)
> db.customIdDemo.insert({ "_id": 1, "StudentName": "Carol" });
WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "E11000 duplicate key error..." } })
3. ใช้ Upsert แทน (ไม่ Error)
> db.customIdDemo.update(
{ "_id": 1 },
{ $set: { "StudentName": "Carol" } },
{ upsert: true }
);
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
4. Insert ใหม่ _id = 2 (Upsert)
> db.customIdDemo.update(
{ "_id": 2 },
{ $set: { "StudentName": "Carol" } },
{ upsert: true }
);
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 2 })
5. ผลลัพธ์สุดท้าย
> db.customIdDemo.find().pretty();
{ "_id" : 1, "StudentName" : "Carol" } // Updated
{ "_id" : 2, "StudentName" : "Carol" } // Inserted
สรุปความแตกต่าง
| Method | _id ซ้ำ | _id ใหม่ |
|---|---|---|
insert() | Error (E11000) | Success |
update({}, {upsert:true}) | Update (Safe) | Insert (Safe) |
Best Practice
- ใช้
updateOne()+upsert: trueแทนinsert()เมื่อมี Custom _id - สร้าง Unique Index บน _id (มีอยู่โดยอัตโนมัติ)
- ใน Application ใช้
findOneAndUpdate()พร้อมupsert: trueสำหรับ atomic read-modify-write