0

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 ?

Erwan Swak
  • 241
  • 4
  • 9

1 Answers1

0

If you are inserting or updating the document and enabled MMAP Storage Engine then there is collection level locking, in this scenario you are safe. But this approach will fail if you have enabled wiredtiger storage engine.

Rohit Jain
  • 2,052
  • 17
  • 19
  • I'm not sure about what you're saying, but the concurrency issue is not in the `find` and `insert/update` operations (which I assume are atomic). It's the fact that my program has to make 2 sequential operations (find, then insert or update), that causes a concurrency problem : nothing guarantees that a program running 2 database queries won't be paused (even if just a few milliseconds) between the 2 operations. – Erwan Swak Sep 23 '15 at 17:29