Benjamin E.
Benjamin E.

Reputation: 5172

MongoDB - replace item in nested array

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?

Upvotes: 1

Views: 403

Answers (1)

enrichz
enrichz

Reputation: 80

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.

Upvotes: 1

Related Questions