Mig og mine kolleger fandt en løsning. Vi kan kalde det tre-trins initialisering .
Husk, at MongoDB garanterer atomiciteten af operationer på et enkelt dokument. Med dette i tankerne kan vi arbejde på følgende måde:
- Prøv at opdatere dokumentet ved at øge tællerne korrekt på et bestemt tidspunkt. Foretag ikke nogen upsert, bare en gammeldags opdateringsoperation. Husk, at udførelsen af en opdateringserklæring returnerer antallet af skrevne dokumenter. Hvis antallet af skrevne dokumenter er større end nul, er du færdig.
- Hvis antallet af dokumenter skrevet af opdateringen er nul, betyder det, at det relative dokument, der skal opdateres, endnu ikke er til stede i samlingen. Prøv at indsætte hele dokumentet for de angivne tags. Sæt alle tællere (feltværdier) til nul. Også udførelsen af en indsæt-erklæring returnerer antallet af skrevne dokumenter. Hvis det returnerer nul eller kaster en undtagelse, skal du ligeglad med det:det betyder, at en anden proces allerede havde indsat dokumentet for de samme tags.
- Udfør den samme opdatering ovenfor igen.
Koden skulle ligne noget, der ligner det følgende kodestykke.
// 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 */);
}
Ovenstående procedure fungerer, hvis en forudsætning indeholder:_id
værdi skal afledes fra andre felter i dokumentet. I vores eksempel, _id
værdien ville være '2013-10-10T23:06:00.000Z-memory_used
. Kun ved brug af denne teknik vil indsatsen ved punkt 2. fejle korrekt.