Domanda

I am new to Mongo. I wanted to atomically upsert a document based on multiple criteria. The document looks like the following:

 {_id:..., hourOfTime:..., total:..., max:..., min:..., last:...}

This is basically hourly aggregation for number of clicks for an item identified by _id. The clicks for each item is is flushed from the application to MongoDB every five seconds. So, the document need to be updated every five seconds.

Here is the case. Lets say at t=t0, we have {_id:"nike", total:123, max:10, min:3, last:9} then at t=t1, I get message {_id:"nike", count: 12}. Now, for _id="nike", I need to do the following,

  1. Increment total by 12
  2. if max < 12, update max=12
  3. if min > 12, update min=12
  4. update last=12

I want all this operation to be atomic. I unable to convert this in one single query. Any help/hint is appreciated.

È stato utile?

Soluzione

This cannot be done with a single query. Here is how I would do it:

  1. Have a field on the document called locked. Run a findAndModify to grab the document if the locked field is false, and set the locked field to the Date() that it is locked at. This will stop other application instances from modifying the document, providing they also check for the locked field.
  2. Modify the document application side, then atomically update it, setting locked to false. As long as anything modifying the document runs a findAndModify on the locked field, this entire modification should be atomic.

Make sure to have a threshold at which a lock times out, so that documents do not become locked indefinitely if a machine blows up. This means that when updating the document the second time (and releasing the lock), the application should make sure that the date in the document is what it expects, to make sure it still has the lock.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top