1

MongoDB does not allow to replace an item in an array in a single operation. Instead it's a pull followed by a push operation.

Unfortunately we have a case where we end up with a race condition on the same item in the array on parallel requests (distributed environment), i.e. 2x pull runs first, then 2x push. This results in duplicate entries, e.g.

{
    "_id": ...,
    "nestedArray": [
        {
            "subId": "1"
        },
        {
            "subId": "1"
        },
        {
            "subId": "2"
        }
    ]
}

Are there any workarounds?

1 Answer 1

1

I usually use an optimistic lock for this situation. To prepare for this, you need to add a version field to your model, which you will increment each time you modify that model. Then you use this method:

Model.findOneAndUpdate(
        {$and: [{_id: <current_id>}, {version: <current_version>}]}, 
        {nestedArray: <new_nested_array>})
  .exec(function(err, result) {
    if(err) {
      // handle error
    }
    if(!result) {
      // the model has been updated in the mean time
    }
    // all is good
});

This means that you first need to get the model and compute the new array <new_nested_array>. This way you can be sure that only one modification will take place for a certain version. Hope I explained myself.

Sign up to request clarification or add additional context in comments.

2 Comments

I guess that's why MongoDB still gets hate from the SQL camp... :) Came up with such a solution before but it felt not right. Thanks
You need to change your whole approach to work with MongoDB. I don't know your requirements, but maybe try to investigate Redis, which can be used in conjunction with MongoDB and supports transactions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.