Welcome to the second post in my "MongoDB Animated 🍩" series, where I provide animated examples and explanations for MongoDB operations that I don't ever want to google again.
In this post, we'll review different strategies for updating elements from embedded arrays.
I'll use the same example collection used in the previous article in this series. It consists of a simple collection of "donut combos" from a donut shop. Each combo has a name and an array of donuts that will be included if the customer chooses that combo. Here's the complete schema:
This sort of operation can come in handy when you migrate to a new schema and your documents have embedded arrays. For example, if you needed to add a new property with a default value to all the array elements.
Another way to take away the glazing could be by removing the property glazing from all donuts in all active documents.
This can be done using the $unset operator in combination with the all positional operator$[]:
Notice that, inside the $unset object, we must define the key (the property we want to remove) and the value, which doesn't impact the operation. In this case, we used "1", but you can also use an empty string, for example: 'donuts.$[].glazing': ''.
Updating the first element with $
You may need to update only the first element of your array. In that case, you should use the positional operator $. This positional operator will allow us to apply changes to the first element that matches the query document (the first parameter of the update method). The array field must be a part of the query document.
By combining the $ positional operator with $set, we can update properties from the first array element that matches our query document.
In the following example we will update the first white donut in every document and change it's color to "pink".
Updating elements that match a filter with $[<identifier>]
To update a set of elements matching certain filters, we must use the filtered positional operator$[<identifier>] where <identifier> is a placeholder for a value that represents a single element of the array.
We must then use the third parameter (options) of the updateMany method to specify a set of arrayFilters. Here we will define the conditions each array element we want to update must meet to be updated.
In the next example, we will change every white donut color to green, only in the active documents.
Combining the filtered positional operator$[<identifier>] (or in our example $[donut]) with the operator $unset, we can remove a property from all elements in the array that match our arrayFilter criteria.
For example, we could remove the color of every white donut in every active document:
I created a repo to try MongoDB queries in memory using Node.js with Jest and MongoDB Node driver. I used tests to execute the query and verify that everything was correctly updated. I also included a logger that prints the updated documents in the console displaying the changes that were applied using diff highlight syntax:
You can find the examples I included in this article in the tests folder:
A simple sample project to try MongoDB queries in memory using Jest
try-mongodb-queries
A simple project to try MongoDB queries in memory using Jest.
Includes a logger that logs the difference between the original test data and the data after the update using diff syntax highlight:
Dependencies
What you need to run this project:
Node.js
(MongoDB is not required because it'll run in memory, handled by the package mongodb-memory-server-core).