When it comes to MongoDB, there might be scenarios where you want to update multiple documents with a single operation. While you could loop through documents and update them individually, updateMany offers a faster, more efficient solution.
In this short tutorial, we'll learn how to use the updateMany operator in MongoDB and optimize queries to achieve the best possible performance.
To build a strong foundation in MongoDB's data handling capabilities using Python, consider exploring the course on Introduction to MongoDB in Python.
Looking at a Practical Example of Updating Multiple MongoDB Documents
To illustrate this concept, let's use a practical example where you might want to update more than one document at a time.
Take the following data as our foundation for the example:
[
{ "name": "Nic Raboy", "title": "Master of Shenanigans", "salary": 50000, "last_raise_date": new Date("2013-06-01") },
{ "name": "Megan Grant", "title": "Word Wrangler", "salary": 125000, "last_raise_date": new Date("2020-12-01") },
{ "name": "Tony Kim", "title": "Alliance Czar", "salary": 80000, "last_raise_date": new Date("2025-02-01") },
];
In the above JSON, we have three employees at a fictional company. The company wants to give everyone a boost in compensation if they haven't received any salary adjustments for a certain time.
To update everyone who qualifies, we can make use of the updateMany operator in MongoDB. To accomplish our task, we might end up with a statement that looks like the following:
db.employees.updateMany(
{
"last_raise_date": {
"$lte": new Date("2024-01-01")
}
},
{
"$mul": { "salary": 1.06 },
"$set": { "last_raise_date": new Date() }
}
);
So, what does the above updateMany operation do?
Taking a step back, the updateMany operator takes two parameters with an optional third parameter.
- The first parameter is an object representing the data we want to filter.
- The second parameter is the changes that we want to make to the results found in the filter.
- The optional third parameter could be
{ “upsert”: true }, which would insert a document if there were no matches.
With that in mind, we are first filtering for all documents where the last_raise_date is earlier than "2024-01-01". Looking back at our very basic dataset, we know we have two of the three documents matching:
[
{ "name": "Nic Raboy", "title": "Master of Shenanigans", "salary": 50000, "last_raise_date": new Date("2013-06-01") },
{ "name": "Megan Grant", "title": "Word Wrangler", "salary": 125000, "last_raise_date": new Date("2020-12-01") }
];
Two different changes will be made to the filtered documents based on the change criteria parameter.
"$mul": { "salary": 1.06 },
First, we're using the $mul operator to multiply one of our fields by a value. In our example, we want to give every qualifying employee a 6% increase in salary. This means we're simply multiplying the current value of the field by 1.06.
To help us document the salary adjustments while also preventing accidental increases in the future, we want to update the last_raise_date to the current date:
"$set": { "last_raise_date": new Date() }
If we were to run our updateMany operation again, nothing would happen because the last_raise_date found in the filter would no longer match any of our three documents.
The above is just an example, but your filter criteria could be much more complex, and likewise, what you plan to change could also be more complex, depending on your use case. You can learn more about MongoDB's updateMany in this video.
In our example, we were working with three small documents. Pretty much no matter what operation we throw at our collection, it will be fast because we won't be working with a whole lot. However, think of a production application where you're working with millions of documents or you’re frequently running the update operation.
If we tried to use the updateMany operator on millions of documents, it might take some time unless we had a proper index established for our filter criteria.
To create an index for our example, we can execute something like this:
db.employees.createIndex({ "last_raise_date": 1 });
You can validate that the updateMany operation is using our index by executing the following:
db.runCommand({
"explain": {
"update": "employees",
"updates": [
{
"q": {
"last_raise_date": {
"$lte": new Date("2024-01-01")
}
},
"u": {
"$mul": { "salary": 1.06 },
"$set": { "last_raise_date": new Date() }
}
}
]
},
"verbosity": "allPlansExecution"
});
In the results, if the inputStage is "IXSCAN," then you're using an index and maximizing your updateMany performance. If the inputStage is "COLLSCAN," then you're not using an index and may need to rethink how you're creating your index based on your filter criteria.
To clear up any confusion, we're using runCommand above to profile our operation of updating multiple documents. If you don't need any profiler information, stick with the much simpler and more elegant updateMany operation.
Conclusion
Updating multiple documents in a single operation in MongoDB is not a difficult task, as seen throughout the tutorial.
Using the updateMany operator, we can define a filter criteria to match our documents against and then a change criteria with a list of changes to make. This updateMany operation can be further optimized by making sure you have a proper index that fits with your filter criteria.
If you’re new to non-relational databases, the Introduction to NoSQL course offers a helpful overview of concepts like document stores.
When it comes to MongoDB, there might be scenarios where you want to update multiple documents with a single operation. While you could loop through documents and update them individually,
updateManyoffers a faster, more efficient solution.In this short tutorial, we'll learn how to use the updateMany operator in MongoDB and optimize queries to achieve the best possible performance.
To build a strong foundation in MongoDB's data handling capabilities using Python, consider exploring the course on Introduction to MongoDB in Python.
Looking at a Practical Example of Updating Multiple MongoDB Documents
To illustrate this concept, let's use a practical example where you might want to update more than one document at a time.
Take the following data as our foundation for the example:
In the above JSON, we have three employees at a fictional company. The company wants to give everyone a boost in compensation if they haven't received any salary adjustments for a certain time.
To update everyone who qualifies, we can make use of the
updateManyoperator in MongoDB. To accomplish our task, we might end up with a statement that looks like the following:So, what does the above
updateManyoperation do?Taking a step back, the
updateManyoperator takes two parameters with an optional third parameter.{ “upsert”: true }, which would insert a document if there were no matches.With that in mind, we are first filtering for all documents where the
last_raise_dateis earlier than "2024-01-01". Looking back at our very basic dataset, we know we have two of the three documents matching:Two different changes will be made to the filtered documents based on the change criteria parameter.
First, we're using the
$muloperator to multiply one of our fields by a value. In our example, we want to give every qualifying employee a 6% increase in salary. This means we're simply multiplying the current value of the field by 1.06.To help us document the salary adjustments while also preventing accidental increases in the future, we want to update the
last_raise_dateto the current date:If we were to run our
updateManyoperation again, nothing would happen because thelast_raise_datefound in the filter would no longer match any of our three documents.The above is just an example, but your filter criteria could be much more complex, and likewise, what you plan to change could also be more complex, depending on your use case. You can learn more about MongoDB's updateMany in this video.
Boost the Performance of Your Update with a MongoDB Index
In our example, we were working with three small documents. Pretty much no matter what operation we throw at our collection, it will be fast because we won't be working with a whole lot. However, think of a production application where you're working with millions of documents or you’re frequently running the update operation.
If we tried to use the
updateManyoperator on millions of documents, it might take some time unless we had a proper index established for our filter criteria.To create an index for our example, we can execute something like this:
You can validate that the
updateManyoperation is using our index by executing the following:In the results, if the
inputStageis "IXSCAN," then you're using an index and maximizing yourupdateManyperformance. If theinputStageis "COLLSCAN," then you're not using an index and may need to rethink how you're creating your index based on your filter criteria.To clear up any confusion, we're using
runCommandabove to profile our operation of updating multiple documents. If you don't need any profiler information, stick with the much simpler and more elegantupdateManyoperation.Conclusion
Updating multiple documents in a single operation in MongoDB is not a difficult task, as seen throughout the tutorial.
Using the
updateManyoperator, we can define a filter criteria to match our documents against and then a change criteria with a list of changes to make. ThisupdateManyoperation can be further optimized by making sure you have a proper index that fits with your filter criteria.If you’re new to non-relational databases, the Introduction to NoSQL course offers a helpful overview of concepts like document stores.