MongoDB provides operators for atomic updates in addition to the normal insert and modify functionality. These operators include, $inc, $set and $unset; and are particularly useful for keeping counters and for thread-safe field updates, which helps resolve data-related concurrency issues in web and multi-threaded applications. If persistence is required and performance is not an issue, these operators can also be a good replacement for single-threaded caching solutions like Redis by providing persistent atomic operations. The use cases for using these operations include, real-time web analytics, leader boards, rate limiting etc.
Spring data provides simple constructs to easily perform these atomic operation on Mongo documents. Below is a sample document, so lets update it atomically.
{ "website_id": 1, "website": "http://example.org", "hits": 1000, "lastAccess": "10-10-2016 09:00", "inactive": true }
Below is the Spring Data code snippet for querying and updating documents. The $inc operator is used to increment or decrement the field value. And $set updates the field value or adds a field in the document if it doesn’t exist. Similarly $unset operator removes the field from the document.
@Autowired MongoOperations mongoOperations; . . mongoOperations.updateFirst(new Query(Criteria.where("website_id").is(1)), new Update() .inc("hits", 1) .set("lastAccess",new Date()) .unset("inactive"), WebsiteVisit.class); .
When the above update operation runs, the document will have “hits” incremented by 1, “lastAccess” set to current date and the “inactive” field removed. All of it thread-safe and atomic. And the resulting document will look something like below:
{ "website_id": 1, "website": "http://example.org", "hits": 1001, "lastAccess": "11-10-2016 22:00" }