Já a moji kolegové jsme našli řešení. Můžeme to nazvat tříkroková inicializace .
Pamatujte, že MongoDB zaručuje atomičnost operací na jediném dokumentu. S ohledem na tuto skutečnost můžeme pracovat následujícím způsobem:
- Zkuste dokument aktualizovat a správně zvýšit čítače v určeném časovém úseku. Nedělejte žádné upsert, pouze staromódní aktualizační operaci. Pamatujte, že provedení příkazu aktualizace vrátí počet zapsaných dokumentů. Pokud je počet napsaných dokumentů větší než nula, jste hotovi.
- Pokud je počet dokumentů zapsaných aktualizací nula, znamená to, že příslušný dokument, který se má aktualizovat, ještě není ve sbírce přítomen. Zkuste vložit celý dokument pro zadané značky. Všechny čítače (hodnoty polí) vynulujte. Také provedení příkazu insert vrátí počet zapsaných dokumentů. Pokud vrátí nulu nebo vyvolá výjimku, nevadí:znamená to, že dokument pro stejné značky již vložil nějaký jiný proces.
- Proveďte stejnou aktualizaci znovu.
Kód by měl vypadat jako něco podobného jako následující fragment kódu.
// 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 */);
}
Výše uvedený postup funguje, pokud platí podmínka:_id
hodnota by měla být odvozena z jiných polí v dokumentu. V našem příkladu _id
hodnota by byla '2013-10-10T23:06:00.000Z-memory_used
. Pouze při použití této techniky vložka v bodě 2 správně selže.