MongoDB Concurrency Question – FindOne, then FindOneAndUpdate Atomicity

  concurrency, database, javascript, mongodb, performance

I would appreciate your time on answering this question before I commit it to some code.

I’ve looked through multiple docs on MongoDB and various forums for the answer to this question, however, I would like to know exactly how certain series of operations execute based on my specific circumstances.

Fundamentally, I would like to perform a Read (findOne) operation on a specific document in a collection within its own shard to obtain its current value, modify it, and then store it back into that document (findOneAndUpdate). That sounds easy enough, however, this specific document can potentially get Written upon during the delay between that Read and then Write operation if I understand properly.

For more context, this is a stock market based application. The shard and collection I am referring to here is a user’s portfolio which contains information such as the stock ticker, the number of shares owned of that stock, and the total cost they have historically paid for it. The issue here is that when a player sells a share, I have to proportionally adjust the historic total cost by multiplying a ratio of (formerOwnedShares – executedSoldShares)/(formerOwnedShares) where formerOwnedShares is information that needs to be Read, processed, then Updated (i.e. the user currently owns 10 shares and has paid $10 for them over time, they sell 5 shares, now they own 5 shares and have paid $5 to maintain a consistent average cost per share).

I am concerned about the delay between the Read and Update operations. Several other areas of code can operate on this portfolio document from other users (such as other users buying/selling shares with them), so there is a very real possibility that the first Read operation pulls information from an older version of this document that has just recently been updated.

Is there any way to process this sort of situation in one atomic operation in order to maintain perfect concurrency? The issue is clearly the result of having to update a document’s value based on that document’s most recent value – which I do not think you can do in a single findOneAndUpdate operation.

Thank you very much for your time.

Source: Ask Javascript Questions