Concurrency control for Mongo collection update

What is the best practice for updating the same document collection in a concurrent environment?

I came across one problem due to concurrency when I executed this server method code to delete a picture object from an array, called from a browser button click event:

var pageItem = PageItems.findOne(pageItemId); var picturesUpdated = _.reject(pageItem.pictures, function(picture){ return picture.pictureId == pictureIdToDelete; }); PageItems.update({ _id: pageItemId }, { $set: { pictures: picturesUpdated } });

It works fine if it’s executed multiple times in slow succession. However in quick succession (or if called whilst iterating in a loop), some pictures fail to delete.

The problem was caused by the fact that it takes some time for the server to execute the _.reject function call, so during that time multiple threads end up reading the same array content.

This kind of code, whilst it may appear fine without error at first glance, is not production-worthy due to failure in a concurrent environment.

I fixed the problem by replacing the code with this:

PageItems.update({ _id: pageItemId }, { $pull: { pictures: { pictureId: pictureIdToDelete } } });

The fix was possible only because MongoDB update has a $pull operator. But what if $pull did not exist?

So the remaining question is: what is the best way to allow a custom object in a collection to be updated by multiple threads in a highly concurrent environment, especially when some custom code needs to execute before each actual .update() call?

It would be good if we could tell threads to wait in a queue and/or use locks and semaphores so that the updates (pre-processing code plus the call to .update()) to the same document object can occur sequentially. Is it possible and practical? What other strategies are there?