Is there any concurrency-friendly way to do this in MongoDB :
I want to insert a document only if the last document sorted by a field have a different value for another field. The goal is to have a collection that only stores transitions, instead of all raw values.
Example :
Here is a collection (with human-friendly timestamps) :
{ "created" : 1000, "lastUpdate" : 1000, "status" : "HEALTHY" }
{ "created" : 2000, "lastUpdate" : 2000, "status" : "ILL" }
{ "created" : 3000, "lastUpdate" : 3000, "status" : "HEALTHY" }
Then let's say I receive a new status A
:
{ timestamp: 9999, "status": "HEALTHY" }
In case A
, there is no status
transition, so I would like to update the collection and have the following :
{ "created" : 1000, "lastUpdate" : 1000, "status" : "HEALTHY" }
{ "created" : 2000, "lastUpdate" : 2000, "status" : "ILL" }
{ "created" : 3000, "lastUpdate" : 9999, "status" : "HEALTHY" }
However, if I receive a new status B
that looks like this :
{ timestamp: 9999, "status": "ILL" }
I want to register a new status
transition, and save a new document in the collection, because B
has a different status
than the most recently updated document (that has a timestamp === 3000
and status === "HEALTHY"
.
The collection will then look like this :
{ "created" : 1000, "lastUpdate" : 1000, "status" : "HEALTHY" }
{ "created" : 2000, "lastUpdate" : 2000, "status" : "ILL" }
{ "created" : 3000, "lastUpdate" : 3000, "status" : "HEALTHY" }
{ "created" : 9999, "lastUpdate" : 9999, "status" : "ILL" }
All I can think of is to make a findOne
to get the most recently updated document, followed by an update
or insert
depending on the in-memory comparison between the fetched document and the newly-received object. But that is not concurrency-friendly, since another process could have inserted another document between my find
and my insert/update
...
Is there a pattern or a mongo feature that I'm not aware of, that could make this possible ?