English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

MongoDB Atomic Operations

Model data for atomic operations

The recommended method to maintain atomicity is to keep all relevant information, which is often updated together into a single document using embedded documents. This will ensure that all updates to a single document are atomic.

Assuming that we have already created a collection named productDetails and inserted a document into it as follows-

>db.createCollection("products")
{  "ok"  : 1 }
>  db.productDetails.insert(
	{
		"_id":1,
		"product_name":  "Samsung  S3",
		"category":  "mobiles",
		"product_total": 5,
		"product_available": 3,
		"product_bought_by":  [
			{
				"customer":  "john",
				"date":  "7-Jan-2014"
			}
			{
				"customer":  "mark",
				"date":  "8-Jan-2014"
			}
		]
	}
)
WriteResult({  "nInserted"  : 1 )
>

In this document, we will embed the information of customers who purchased products into the product_bought_by field. Now, every time a new customer purchases a product, we will first use the product_available field to check if the product is still available. If it is available, we will reduce the value of the product_available field and insert a new embedded document of the new customer into the product_bought_by field. We will use the findAndModify command for this feature because the process of searching and updating documents is the same.

>db.products.findAndModify({ 
   query:{_id:2,product_available:{$gt:0}}, 
   update:{ 
      $inc:{product_available:-1} 
      $push:{product_bought_by:{customer:"rob",date:"9-Jan-2014"}} 
   }    
)

We adopt the method of embedding documents and using findAndModify queries to ensure that product purchase information is only updated when the product is available. The entire transaction is atomic and within the same query.

On the contrary, consider the following scenario: We may separately retain the availability of the product and information about who purchased the product. In this case, we will use the first query to check the availability of the product first. Then, in the second query, we will update the purchase information. However, it is possible that between the execution of these two queries, other users have already purchased the product, and the product is no longer available. Without knowing this, our second query will update the purchase information based on the result of our first query. This will make the database inconsistent because we have already sold an unavailable product.