Để thực hiện **upsert hàng loạt** (cập nhật nếu tồn tại, chèn mới nếu không) cho nhiều tài liệu cùng lúc, MongoDB cung cấp **Bulk Operations API**: initializeUnorderedBulkOp() (hoặc initializeOrderedBulkOp()). Cách này hiệu quả hơn nhiều so với vòng lặp client-side.
1. Tạo dữ liệu: 3 Chris, 1 David
> db.demo425.insertOne({ "Name": "Chris", "Age": 21 });
> db.demo425.insertOne({ "Name": "David", "Age": 23 });
> db.demo425.insertOne({ "Name": "Chris", "Age": 21 });
> db.demo425.insertOne({ "Name": "Chris", "Age": 21 });
2. Bulk Upsert: Với Name="Chris", set Name="Robert", Age=23, setOnInsert id=101
> var b1 = db.demo425.initializeUnorderedBulkOp();
> b1.find({ Name: "Chris" }).upsert().update({
$setOnInsert: { id: 101 }, // Chỉ set khi insert mới (upsert)
$set: { Name: "Robert", Age: 23 } // Luôn set khi update hoặc upsert
});
> b1.execute();
3. Kết quả thực thi
BulkWriteResult({
"nMatched": 3, "nModified": 3, "nUpserted": 0, "nInserted": 0, ...
})
Khớp 3 tài liệu Chris, update tất cả 3 thành Robert/23. Không upsert vì đã tồn tại.
4. Dữ liệu sau bulk
> db.demo425.find();
Kết quả: 3 tài liệu Robert (Age 23), 1 David (Age 23).
Cách hiện đại (MongoDB 3.2+): bulkWrite() thay Bulk API cũ
db.demo425.bulkWrite([
{
updateMany: {
filter: { Name: "Chris" },
update: { $set: { Name: "Robert", Age: 23 } },
upsert: false
}
}
], { ordered: false });
Lưu ý: $setOnInsert chỉ áp dụng khi upsert: true VÀ tài liệu không tồn tại (insert mới). Trong ví dụ này upsert() được gọi nhưng không insert mới vì filter khớp 3 doc.