Atomic find and modify operations

In Chapter 2, Command-line Operations and Indexes, we had some recipes that explained various CRUD operations we perform in MongoDB. There was one concept that we didn't cover and it is atomically find and modify documents. Modification consists of both update and delete operations. In this recipe, we will go through the basics of MongoDB's findAndModify operation. In the next recipe, we will use this method to implement a counter.

Getting ready

Look at the recipe Installing single node MongoDB in Chapter 1, Installing and Starting the Server and start a single instance of MongoDB. That is the only prerequisite for this recipe. Start a mongo shell and connect to the started server.

How to do it…

  1. We will test a document in atomicOperationsTest collection. Execute the following from the shell:
    > db.atomicOperationsTest.drop()
    > db.atomicOperationsTest.insert({i:1})
    
  2. Execute the following from the mongo shell and observe the output:
    > db.atomicOperationsTest.findAndModify({
        query: {i: 1},
        update: {$set : {text : 'Test String'}},
        new: false
      }
    )
    
  3. We will execute another one this time but with slightly different parameters; observe the output for this operation:
    > db.atomicOperationsTest.findAndModify({
        query: {i: 1},
        update: {$set : {text : 'Updated String'}}, fields: {i: 1, text :1, _id:0},
        new: true
      }
    )
    
  4. We will execute another update this time that would upsert the document as follows:
    >db.atomicOperationsTest.findAndModify({
        query: {i: 2},
        update: {$set : {text : 'Test String'}},
        fields: {i: 1, text :1, _id:0},
        upsert: true,
        new: true
      }
    )
    
  5. Now, query the collection once as follows and see the documents present:
    > db.atomicOperationsTest.find().pretty()
    
  6. We will finally execute the delete as follows:
    >db.atomicOperationsTest.findAndModify({
        query: {i: 2},
        remove: true,
        fields: {i: 1, text :1, _id:0},
        new: false
      }
    )
    

How it works…

If we perform find and update operations independently by first finding the document and then updating it in MongoDB, the results might not be as expected. There might be an interleaving update between the find and the update operations, which may have changed the document state. In some of the specific use cases, like implementing atomic counters, this is not acceptable and thus we need a way to atomically find, update, and return a document. The returned value is either the one before the update is applied or after the update is applied and is decided by the invoking client.

Now that we have executed the steps in the preceding section, let's see what we actually did and what all these fields in the JSON document passed as the parameter to the findAndModify operation mean. Starting with step 3, we gave a document as a parameter to the findAndModify function that contains the fields query, update, and new.

The query field specifies the search parameters that would be used to find the document and the update field contains the modifications that need to be applied. The third field, new, if set to true, tells MongoDB to return the updated document.

In step 4, we actually added a new field to the document passed as a parameter called fields that is used to select a limited set of fields from the result document returned. Also, the value of the field new is true, which tells that we want the updated document that is, the one after the update operation is executed and not the one before.

In step 5 contains a new field called upsert, which upserts (update + insert) the document. That is, if the document with the given query is found, it is updated else a new one is created and updated. If the document didn't exist and an upsert happened, having the value of the parameter new as false will return null. This is because there was nothing present before the update operation was executed.

Finally, in step 7, instead of the update field, we used the remove field with the value true indicating that the document is to be removed. Also, the value of the new field is false, which means that we expect the document that got deleted.

See also

An interesting use case of atomic FindandModify operations is developing an atomic counter in Mongo. In our next recipe, we will see how to implement this use case.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset