: From Installation to Implementation
Part 5 in an introduction to using – and making the most of – MongoDB

Previously on MongoDB
In part four, we set up both Insert and Delete endpoints for our MongoDB collections. We did this using a combination of pymongo and pydantic. After connecting to the Database, we used the FastAPI endpoints to pass our new records for inserting into our database or passing the ID to delete. For testing, we used Postman.
This Time on MongoDB
After considering for a while, I decided how I want to create the update endpoints. Recall the updates will be slightly more difficult than simply selecting the items to update, as we have embedded collections in a couple of collections. Please note, this may not be the simplest solution or even the correct way to perform an update in the case of embedded collections. This will simply be my research and findings. If you may have ideas on how to perform an update more effectively than my solution, I would love to learn more about it, so please feel free to share in the comments. For now, we will have to learn how to update in Mongodb first.
Updating Collections in MongoDB
If you have trouble connecting, recall you have to stop and restart mongod. We covered this in previous parts, so please look back if you need a refresher.
Using our Receipts database, we should take a look at the Grocery collection, as it can be used to show an example of a regular update and the issue of an embedded document:

Now that we have the ID, we can use the update command to change the total. To do so, simply use the "update" command with a series of arguments. The first set to send will be a JSON object of what conditions should be met to update. In terms of relational databases, this would be comparable to the WHERE statement. The second set will be what keys you want to change, then the values you want to replace with. For our first example, we will only update the total:
db.Grocery.update({_id:ObjectId("<IdHere>")}, {$set: "Total": 9.77}})

Our next update will display the issue of the embedded document. If we would want to specify explicitly by using the names like so, we would receive no updates:
db.Grocery.update({_id:ObjectId("<IdHere>"), ProductName: "Cat Food Can"}, {$set: {"UnitPrice": 0.70}})

No documents were found, but we know from the data that one exists. The issue is that in the original document, there is no "ProductName". There is only a "Items" that would then contain "ProductName".
A little more complicated, we can use an element match function within the Items object. This way, we can specify which product should be updated in the items. Within the set portion, we will call the Items object, then declare which value should be updated:
db.Grocery.update({_id:ObjectId("<IdHere>"), Items:{$elemMatch:{ProductName: "Cat Food Can"}}}, {$set: {"Items.$.UnitPrice": 0.70}})

Now review the document once again to verify:

Recall that we have another Grocery document containing only one Item. But what if we forgot to add an item to that list? We would need to find a way to update the list of items as a whole. So first we will decide to update the Grocery list with only one item:

To add without harming any existing items, we can use a "push" command. This is similar to a push like what is done to a list, simply adding the new item to the end and maintaining the existing items. Now we can give that a try:
db.Grocery.update({_id:ObjectId("<IdHere>")}, {$push: {Items: {ProductName: "Bubble Gum", UnitPrice: 0.99, "Quantity": 1}}})

To be sure everything is right, check our entry once again:

If you find that you did not want to add the item, there is a way to reverse our "push". We can instead use a "pull". By using this, MongoDB will search for whichever product name is specified, and will then remove that embedded document.
db.Grocery.update({_id:ObjectId("<IdHere>")}, {$pull: {Items: {ProductName: "Bubble Gum"}}})

Now check our data once again:

One last basic update would be in the case where all items simply need to be replaced. This could be in the case of having the wrong items on a receipt and needing to update to the correct items. For this type, we can just use a "set". Recall that setting a value will override any previous data, so be sure you are updating the document you want to alter. To change the elements of the last Grocery list we altered, we will set the Items embedded documents to a new set of embedded documents.
db.Grocery.update({_id:ObjectId("<IdHere>")}, {$set: {Items: [{ProductName: "Bananas", UnitPrice: 0.58, Quantity: 2}, {ProductName: "Baby Food", UnitPrice: 0.87, Quantity: 1}]}})

When we check our entry again, the old data will no longer be present. Instead, the new data should have replaced it:

There are also options to update multiple documents at a time, as well as multiple fields within each document. However, for our purposes, we can use the basic updates we have already learned. If we should need multiple updates at a later time, we can learn then. For now, we will be able to move onto the FastAPI portion of the updates, as pymongo will be different than traditional Mongo anyway.
Conclusion
Before being able to move onto the update FastAPI endpoints, we first needed to learn how to perform updates within MongoDB. We talked about the syntax, which involved several different methods of updating.
First, we learned how to do a standard update with the "set" statement. Next, we used the same statement to target embedded document elements. After this, we discussed an issue with updating if the original documents were to remain, and a new document needed to be added to the embedded JSON object. In doing so, we used a "push" statement to maintain existing data while adding the new Item entry. To counteract adding an Item entry, we also learned how to remove the embedded document by using a "pull" command to delete only a specified Item entry. This way, any other elements would remain. Finally, we learned how to reset every document inside the Items list, should the wrong items have been added to a particular receipt, or if you just want to start fresh. This was achieved by using the "set" command once more. As a note, we discussed that there is the possibility to update multiple documents or multiple fields. However, this was out of our project scope, for the time being, so we skipped that portion.
So we did not get to any of the FastAPI endpoints this time, but I feel we learned some valuable information about how to update in MongoDB. Next time, we can use our knowledge about how updates work to determine how to correctly set up our endpoints. Until then, cheers!
Read all my articles for free with my weekly newsletter, thanks!
Want to read all articles on Medium? Become a Medium member today!
| Check out some of my recent articles
I Fell in Love With FastAPI, But I Made Some Mistakes
Trying Out the Docker Hub CLI Tool
db.collection.update() – MongoDB Manual
Updating embedded document property in Mongodb
MongoDB update one or more fields of one or all documents
Insert an embedded document to a new field in mongodb document