MongoDB - атомарные операции

Данные модели для атомарных операций

Рекомендуемый подход к поддержанию атомарности - хранить всю связанную информацию, которая часто обновляется вместе в одном документе с использованием embedded documents. Это обеспечит атомарность всех обновлений для одного документа.

Предположим, мы создали коллекцию с именем productDetails и вставили в нее документы, как показано ниже -

>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 })
>

В этом документе мы встроили информацию о клиенте, который покупает продукт, в product_bought_byполе. Теперь, когда новый клиент покупает продукт, мы сначала проверяем, доступен ли он, используяproduct_availableполе. Если возможно, мы уменьшим значение поля product_available, а также вставим встроенный документ нового клиента в поле product_bought_by. Мы будем использоватьfindAndModify для этой функции, потому что она ищет и обновляет документ одновременно.

>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"}} 
   }    
})

Наш подход встроенного документа и использования запроса findAndModify гарантирует, что информация о покупке продукта обновляется только в том случае, если продукт доступен. И вся эта транзакция, находящаяся в одном запросе, является атомарной.

В отличие от этого, рассмотрим сценарий, в котором мы могли сохранить доступность продукта и информацию о том, кто купил продукт, отдельно. В этом случае мы сначала проверим, доступен ли товар, с помощью первого запроса. Затем во втором запросе мы обновим информацию о покупке. Однако возможно, что между выполнением этих двух запросов какой-то другой пользователь приобрел продукт, и он больше не доступен. Не зная об этом, наш второй запрос обновит информацию о покупке на основе результата нашего первого запроса. Это сделает базу данных несовместимой, потому что мы продали продукт, которого нет в наличии.