Domanda

Let's say I have a schema A in mongoose. It looks like this:

{
    arr: [{
        num: Number,
        text: String
    }]
}

Now I want to perform the following action:

  1. Select an A namely a.

  2. Get the actual count of a.arr's items.

  3. Add a new element to a.arr, with the count and a text.

My implementation:

A.findOne({_id: someId}, function(err, a) {
    var count = a.arr.length;
    a.push({
        count: count,
        text: 'some text'
    });
    a.save(...)
});

Works fine so far. But my problem: If I execute that concurrent, let's say with 5 processes, some processes execute findOne before the others saved. So count is 0 for the first few, and then when they have saved, it gets immediately 3 or 4 for the next processes.

But I want that to execute serial.

How to achieve that?

Thanks!

È stato utile?

Soluzione

There is no transaction support in mongo, but you could implement two phase commits as described in http://cookbook.mongodb.org/patterns/perform-two-phase-commits/

Alternatively you could implement some coordination between processes, fx assign data ranges to specific processes if data supports this scenario.

Edit: in very simple form you could implement some optimistic document locking by adding property lockProcessId and use following command sequence:

db.A.findAndModify({_id: someId, lockProcessId:{$exists:false}},{$set:{lockProcessId: someProcessId},{new:true}}

db.A.findAndModify({_id: someId, lockProcessId:someProcessId},{$push:{arr:{ count: count,text:'some text'}},$unset:{lockProcessId:1}})

If first query returns nothing, process should skip this document, otherwise it should run second query

However if some process dies in the middle you could have some documents locked, probably you need some scheduler to clear locked states.

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