Saya dan rekan saya menemukan solusi. Kita bisa menyebutnya inisialisasi tiga langkah .
Ingat bahwa MongoDB menjamin atomisitas operasi pada satu dokumen. Dengan mengingat fakta ini, kami dapat beroperasi dengan cara berikut:
- Cobalah untuk memperbarui dokumen, menambah penghitung dengan benar pada potongan waktu yang ditentukan. Jangan lakukan upsert apa pun, hanya operasi pembaruan kuno. Ingatlah bahwa eksekusi pernyataan pembaruan mengembalikan jumlah dokumen yang ditulis. Jika jumlah dokumen yang ditulis lebih besar dari nol, Anda selesai.
- Jika jumlah dokumen yang ditulis oleh pembaruan adalah nol, berarti dokumen relatif yang akan diperbarui belum ada dalam koleksi. Cobalah untuk memasukkan seluruh dokumen untuk tag yang ditentukan. Letakkan semua penghitung (nilai bidang) ke nol. Juga pelaksanaan pernyataan insert mengembalikan jumlah dokumen yang ditulis. Jika mengembalikan nol atau melempar pengecualian, tidak apa-apa:itu berarti bahwa beberapa proses lain telah memasukkan dokumen untuk tag yang sama.
- Jalankan lagi pembaruan yang sama di atas.
Kode akan terlihat seperti sesuatu yang mirip dengan cuplikan kode berikut.
// Firt of all, try the update
var result = db.test.update(
{timestamp_minute: ISODate("2013-10-10T23:06:00.000Z"), type: “memory_used”},
{$inc: {"values.39": 1}},
{upsert: false}
);
// If the update do not succeed, then try to insert the document
if (result.nModified === 0) {
try {
db.test.insert(/* Put here the whole document */);
} catch (err) {
console.log(err);
}
// Here we are sure that the document exists.
// Retry to execute the update statement
db.test.update(/* Same update as above */);
}
Prosedur di atas berfungsi jika prasyarat berlaku:_id
nilai harus diturunkan dari bidang lain dalam dokumen. Dalam contoh kita, _id
nilainya adalah '2013-10-10T23:06:00.000Z-memory_used
. Hanya dengan menggunakan teknik ini, penyisipan pada poin 2. akan benar-benar gagal.