How to Update Multiple MongoDB Documents in Python

Introduction

If you use MongoDB to store and manage your data, there will be many times when you need to update multiple documents in a collection at once. In the past, the only method available to accomplish this was the update() method– you would need to use the multi flag with this method to change multiple documents at a time. Today, it’s easier than ever to update documents with PyMongo using the update_many() method. In this article, we’ll explain how to update documents in MongoDB with Python, using the update_many() API call.

Prerequisites

Before we look at the Python code needed to update documents in MongoDB, it’s important to review the prerequisites. The following system requirements exist for this task:

  • You must have MongoDB installed and running, and you’ll need to have some documents in a collection that can be updated when you run the example code.

  • You’ll need to confirm that Python3 and its pip3 package manager are both installed and working. You can enter the command: pip3 --version into a terminal window to verify that PIP is installed, and you can use python3 -V to check the version of Python 3. In this article, all the examples use Python 3, because Python 2 has been deprecated.

  • You’ll need to install the PyMongo client driver for MongoDB using pip3:

pip3 install pymongo
  • You’ll also need to install the BSON library for MongoDB ObjectIds if you intend to query and update a document by its "_id" field. This library can be installed using PIP:
pip3 install bson
  • It’s helpful to have a working knowledge of Python in order to understand the code examples in this article.

Access a MongoDB collection with documents to update

Now that we’ve covered the system requirements, let’s take a look at the code. The first thing we’ll do is import the PyMongo library into the Python script. Then, we’ll create a new client instance of the driver:

# import the MongoClient class of the PyMongo library
from pymongo import MongoClient

# create a client instance of the MongoClient class
mongo_client = MongoClient('mongodb://localhost:27017')

We can then use our MongoDB client instance to access a database and one of its collections:

db = mongo_client.some_database
col = db["some_collection"]

It’s possible to access the collection class’s methods without actually creating a collection instance. You can do this by accessing it as an attribute of the database object.

In the following example, we access a collection through the database object, and then iterate over the Cursor object to examine its documents:

# find all documents
cursor = db.some_collection.find()

# iterate over the Cursor obj for documents
for doc in enumerate(cursor):
    print (doc) # returns a tuple

Look for some MongoDB documents to update with PyMongo

Next, let’s look at an example where we use the count_documents() method to verify that the collection has some documents on it. Be sure to pass a query in the form of a dictionary to the method (or simply pass {} to find all of the collection’s documents), otherwise Python will raise a TypeError exception :

total_docs = col.count_documents({})
print (col.name, "has", total_docs, "total documents.")

Greater than $regex query to find MongoDB documents

The following code shows a simple $regex query used to find documents where the "num" field has an integer value greater than 0:

num_query = {"num":{ "$gt" : 0} }
find_result = db["Some Collection"].find( query )

# iterate the docs returned by find()
for doc in find_result:
    print (doc, "\n")

The query filters for the update_many() method are very similar to the one shown in the above find() query to look for documents.

Using MongoDB’s Update API methods in PyMongo

The API used to update documents works in much the same way as the Mongo Shell methods updateOne() and updateMany().

The update() method is deprecated in favor of update_one() and update_many()

If you’re familiar with older versions of MongoDB that offer the update() method, please note that as of MongoDB version 3.x and above, the update() method has been deprecated. The main difference is that you’ll need to plan ahead before writing your code to determine if the API call will need to update just one document, or many.

>NOTE: The save() method has also been deprecated in newer versions of MongoDB. Use the update_one() or update_many() methods instead.

The MongoDB update operators for document fields

There are few different MongoDB update operators that can be used to modify a document’s fields in the various Update method calls. Let’s take a quick look at each of them:

Update Operators for Setting Values:

$set — As the name suggests, this operator simply sets a field’s value. $setOnInsert — This operator only updates a field’s value if it’s a new document insertion. $unset — This operator removes the field and its value in the document.

Numerical-based Operators:

$inc — This operator is used to change a field’s numerical value by an incremental value that’s specified in the parameter. $min and $max — These operators are used to update a document’s field only if the numerical value falls within the specified min or max range. $mul — This operator multiplies a document’s numerical value by a specified amount.

Other Update Operators:

$currentDate — This operator will change a field’s value to match the current date. $rename — This operator will change a field’s name.

Aggregation Operators:

$in — (only available since version 3.4 of MongoDB) $or — This operator is used to update documents that match any of several parameters.

Use the update_many() method to update multiple MongoDB documents

The update_many() method accepts a parameter in the form of dictionary object with multiple keys nested inside a list.

The next example updates any document where the "num" field has an integer value that is greater than 100. If a document meets this condition, it will be given a new field called "num check" that has a value of True:

# update many with "num" field greater than 100
result = col.update_many(
    {
        "num": { "$gt": 100 } },
        {
            "$set": { "num check" : True }
        }
)

Let’s print out the various attributes of the pymongo.results.UpdateResult object to verify that our update operation was successful:

# print attributes of the results object
print ("raw:", result.raw_result)
print ("acknowledged:", result.acknowledged)
print ("matched_count:", result.matched_count)

Use the MongoDB Compass UI to verify that the update_many() call in Python was successful

Screenshot of MongoDB Compass checking a collection's documents after update_many() method call in Python

Use the $or operator to update several documents in PyMongo

The "$or" operator update option is an efficient way to pass multiple queries and update several documents at a time.

Use the "$or"operator to update several documents by using the BSON ObjectId as parameters

Let’s look at an example that uses the "$or" operator to pass several BSON ObjectIds. This allows us to update two specfic documents (be sure to import the ObjectId module in your script to avoid getting a NameError exception):

# pass multiple BSON IDs to the query's filter
result = col.update_many({"$or": [
        {"_id" : ObjectId("5cfa4c0ad9edff487939ddb2")},
        {"_id" : ObjectId("5cf8c65b8dbf4d4c309c3f38")}
    ]},
    {'$currentDate': {'date': True}},
    upsert = True
)

Set the upsert flag option to True so that MongoDB inserts a new document if none matching the query exists

Note that this example uses the upsert flag. This ensures that a document will be created, with the specified _id, if none exists. After the API call, both documents were given a "date" field with a date string as the value:

"date" : 2019-06-09T11:28:48.714+00:00

You can examine the returned result object to confirm that the API call was successful, and you can also print the upserted_id attribute to see if a new document was inserted:

# print attributes of the results object
print ("raw:", result.raw_result)
print ("acknowledged:", result.acknowledged)
print ("matched_count:", result.matched_count)

# check for any new upserted IDs
print ("upserted_id:", result.upserted_id)

Use the $unset operator to remove a specific field name from all documents in a MongoDB collection

Here’s an example of the update_many() call that uses the $unset operator to remove a specific field from all MongoDB documents that match a filter. To remove, or “unset”, a field, simply set its value as an empty string:

# use the update_many() method to unset fields with $unset
result = col.update_many( {"date": "}, {"$unset": {"date":"}} )

This operator, along with the $rename operator, offers a convenient way to change the fields within a MongoDB collection. The following example shows an API call used to rename the fields of MongoDB documents that match the filter query:

# use the update_many() method to modify fields with $rename
result = col.update_many(
    {"date": ""},
    {"$rename": {"date": "start date"}}
)

Conclusion

When you want to update multiple MongoDB documents at a time, the PyMongo driver makes it easy to accomplish this task within a Python script. The examples we provided throughout this tutorial showed how to use the update_many() method to update the contents of a field, add a new field or even remove a field from any documents that match a specified query filter. Armed with these examples and instructions, you’ll have no trouble updating documents in MongoDB using Python.

Just the Code

Throughout this article, we’ve shown you the example code one section at a time. Included below is the complete Python script used to update multiple MongoDB documents:

#!/usr/bin/env python3
#-*- coding: utf-8 -*-

# import the MongoClient class of the PyMongo library
from pymongo import MongoClient

# import ObjectID from MongoDB's BSON library
# (use pip3 to install bson)
from bson import ObjectId

# create a client instance of the MongoClient class
mongo_client = MongoClient('mongodb://localhost:27017')

# create database and collection instances
db = mongo_client.some_database
col = db["some_collection"]

# see if the MongoDB collection has documents on it
total_docs = col.count_documents({})
print (col.name, "has", total_docs, "total documents.")

# make a $regex query to find docs with "num" field
num_query = {"num":{ "$gt" : 0} }
find_result = db["Some Collection"].find( query )

# iterate the docs returned by find()
for doc in find_result:
    print (doc, "\n")

"""
USE update_many() TO UPDATE MULTIPLE DOCUMENTS
ON A MONGODB COLLECTION
"""


# update many with "num" field greater than 100
result = col.update_many(
    {
        "num": { "$gt": 100 } },
        {
            "$set": { "num check" : True }
        }
);

# print attributes of the results object
print ("raw:", result.raw_result)
print ("acknowledged:", result.acknowledged)
print ("matched_count:", result.matched_count)


# pass multiple BSON IDs to the query's filter
result = col.update_many({"$or": [
        {"_id" : ObjectId("5cfa4c0ad9edff487939ddb2")},
        {"_id" : ObjectId("5cf8c65b8dbf4d4c309c3f38")}
    ]},
    {'$currentDate': {'date': True}},
    upsert = True # use upsert to insert new doc
)

# print attributes of the results object
print ("raw:", result.raw_result)
print ("acknowledged:", result.acknowledged)
print ("matched_count:", result.matched_count)

# check for any new upserted IDs
print ("upserted_id:", result.upserted_id)

# use the update_many() method to unset fields $unset
result = col.update_many( {"date": ""}, {"$unset": {"date":""}} )

# use the update_many() method to modify fields with $rename
result = col.update_many(
    {"date": ""},
    {"$rename": {"date": "start date"}}
)

Pilot the ObjectRocket Platform Free!

Try Fully-Managed CockroachDB, Elasticsearch, MongoDB, PostgreSQL (Beta) or Redis.

Get Started

Keep in the know!

Subscribe to our emails and we’ll let you know what’s going on at ObjectRocket. We hate spam and make it easy to unsubscribe.