Types of Update operations in MongoDB using Spring Boot

Dhaval Simaria
Geek Culture
Published in
6 min readFeb 19, 2022

When I started working with MongoDB and Java, I used to frequently face this difficulty in picking the correct update operation out of the various methods provided by MongoDB. Even during Code review, I used to get comments from the reviewer suggesting to use say, ‘findAndModify()’ instead of ‘updateMulti()’. And these experiences became the reason for me to write this article.

Here we will discuss different types of update operations in MongoDB, and how they differ from each other.

Image Source: FOSS Linux from Google search

I have used Java-8 with the Spring-Boot framework to implement use-cases which can be found here @ Github-MongoOperations.

We will be evaluating all the ‘Update operations’ based on five parameters:
1. Search Criteria
2. Input Update value (Entire Document OR Update Definition)
3. Return value (Entire Document OR Update Result stats)
4. Default behavior if matching document(s) not found.
(Insert/Does not Insert/Flexible)
5. Delta update

We will be using a simple ‘City’ document object to interact with the Mongo database.

‘City’ document in Mongo database

Now that we have the context set, let’s dive into our topic.

save():

save() method does not accept any parameters or criteria to find the document that has to be updated. It by default tries to find the document using ‘_id’ if provided with the document object.

If the document is found, the save() method updates the document else creates a new one.

save() method returns the updated/newly created document object.

The disadvantage with the save() method is that we always have to provide the whole Document object as an input parameter even if we want to update only 1 or 2 fields out of 20 fields. Meaning the save() method does not allow delta updates.

MongoTemplate ‘save’ method. MongoRepository ‘save’ method is also used in a similar manner.

saveAll():

saveAll() method is exactly similar to the save() method except for two things.

Instead of one document object, it takes a collection of document objects like List<City> as an input parameter and returns a collection of updated/inserted document objects like List<City>.

upsert():

upsert() method is similar to the save() method in the way that it updates the document if found, else creates a new one based on the data provided.

But there are a couple of difference b/w upsert() & save() method.
Unlike the save() method, upsert() accepts criteria on other fields apart from ‘_id’ to find the document to be updated.

upsert() returns an acknowledgment object containing details of update operation like ‘upsertedId’, ‘matchedCount’, ‘modifiedCount’.

upsert() does not accept the entire Document object but only the UpdateDefinition containing the details of which all fields have to be updated.

This functionality has its own advantage & disadvantage.

The advantage here is that we can do a delta update. Meaning if an object contains 20 fields, then it is possible to explicitly update any 2 or 3 or n number of fields. We need not provide the whole Document object again to persist in our changes.

The disadvantage here is that if no document is found for a given criterion, then upsert() will create an object with only the fields provided in the UpdateDefinition. This may result in adding incomplete/corrupted data into the database.

MongoTemplate Upsert method

findAndModify():

findAndModify() brings the best of both upsert() and save() method method.

Like the upsert() method, the findAndModify() method also accepts criteria on other fields apart from ‘_id’ to find the document to be updated.

We can also do delta update here, like the upsert() method.

findAndModify() does not accept the entire Document object but only the UpdateDefinition containing the details of which all fields have to be updated

Like save() method, findAndModify() method returns the entire document object. Additionally, we get the flexibility to mention if we want the old, pre-update document object or the new, post-update document object as the return value.

We can choose if we want to insert the new document or not if no document is found matching to search query by providing the ‘upsert(true)’ option to findAndModify() method.

MongoTemplate FindAndModify method

findAndReplace():

findAndReplace() allows us to find a document using a query over any field.
Once the document is found, it replaces that document using the new document that we have provided in the request.

We can choose if we want to insert the new document or not if no document is found matching to search query by providing the ‘upsert()’ option to findAndReplace() method.

We can also choose if we want the updated document as the return value or not by providing the ‘returnNew()’ option to findAndReplace() method.

Delta update is not possible since we need to provide the entire document which is used to replace the existing document.

MongoTemplate FindAndReplace method

updateFirst():

updateFirst() accepts criteria on other fields apart from ‘_id’ to find the document to be updated.

We can also do delta updates here, like the upsert() method.

Like upsert() method, the updateFirst() returns an acknowledgement object containing details of update operation like ‘upsertedId’, ‘matchedCount’, ‘modifiedCount’.

But, if no matching document is found, it will not create a new document in the database based on the fields provided in the UpdateDefinition.

The only difference between the updateFirst() and other delta update operations is that it will update only the first document out of all the documents that match the update criteria.

MongoTemplate UpdateFirst method

updateMulti():

updateMulti() is exactly similar to the updateFirst() except for one thing. Unlike the updateFirst(), it will update all the documents that match the update criteria.

MongoTemplate UpdateMulti method

BulkOps Using UpdateOne():

BulkOps Using UpdateOne() takes one or more inputs parameters that are used with separate queries. We also need to provide UpdateDefinitions corresponding to each search query. Meaning, we will have to provide ‘Pairs’ of the search queries and UpdateDefintions to indicate what data should be updated when a particular search query satisfies.

It also implies that all the bulk Update operations are delta updates and unlike save() and findAndReplace() methods, it does not accept entire documents as input.

‘First’ document that satisfies each query individually will be updated.

If no matching document is found, it will not create a new document in the database based on the fields provided in the UpdateDefinition.

Update for all the queries are mutually exclusive, i.e. a document does not have to satisfy multiple queries.

Like updateFirst() method, the BulkOps Using UpdateOne() returns an acknowledgement object containing details of update operation like ‘upsertedId’, ‘matchedCount’, ‘modifiedCount’.

MongoTemplate BulkOps using UpdateOne method

BulkOps Using UpdateMulti():

BulkOps Using UpdateMulti() exactly similar to BulkOps Using UpdateOne() except for one thing. Unlike BulkOps Using UpdateOne(), it will update all the documents that match any one of the queries from the update criteria.

MongoTemplate BulkOps using UpdateMulti method

References
Spring Data MongoDB — Reference Documentation

Spring Blog — Text Search

MongoDB BulkWrite Documentation

Spring Docs — Mongo Bulk Operations

Conclusion
Now that we have discussed various MongoDB update operations, I hope next time you will be able to select an appropriate update method out of the above methods by considering their pros and cons.

The complete code of the above examples can be found in Github-MongoOperations.

Cheers!!

--

--

Dhaval Simaria
Geek Culture

Experienced Software Engineer | Beginner Data Scientist