I could write the introduction to this article presenting MongoDB — what it is and what its features are. Still, if you have stumbled upon this article, you probably already know all of this, and if you don’t, then go and search the web for one of many articles describing MongoDB, it’s been done so many times that it makes no point for me to do this again, so let’s get straight to the point.
Our working dataset
We’ll be working on a collection of companies, each consisting of a name and list of its employees along with their role, salary, and city where they work.
Updating the salary of all employees
with `$` all positional operator
Suppose our companies’ workers have been doing such good work that we’ve decided to give them a raise of 500. To update the field in all array elements, we’re going to use an all-positional operator `$`
let’s check our results:
So far, so good. Let’s give our employees another raise. Of course, not to everyone, only those employees whose salary is less than or equal to 8000. So, we need to construct a Mongo query to filter out employees earning more than 8000. Our first thought might be to use a `$elemMatch` operator to match those records with array elements matching criteria, so let’s do it.
With the usage of `$elemMatch` and we might write a query as one below:
And MongoDB will happily announce that it has modified our documents:
So, let’s verify if everything is okay by fetching companies from the collection
Uh-oh. It seems we have accidentally given all our employees a raise instead of only a selected group. Why is that?
According to MongoDB Manual definition of $elemMatch goes:
The `$elemMatch` operator matches documents that contain an array field with at least one element that matches all the specified query criteria.
So this means that ‘$elemMatch’ isn’t suitable for our needs. So do we have to update every position manually?
ArrayFilters to the rescue
Fortunately no! MongoDB supports updating filtered array elements through array filters. The syntax for using them is as follows:
Let’s fix the data by removing the last 500 raise and write a new update operation with arrayFilter to raise salary by 500 only for those earning no more than 7500:
We add an arrayFilters array with the filters specified as `<identifier>` and use this identifier in the update query. Let’s see the results after the update:
Now, with the usage of arrayFilters, we can do more elaborate updates. For example, if we would like to modify the salary of workers in Warsaw, we can use array filters to achieve this:
And the result:
Nested arrays and the arrayFilters
Using arrayFilters we can easily update even nested arrays. Suppose we have data like this:
A list of departments containing a list of its’ managers and department headcount. Let’s say we want to increase the salary of managers earning less than 4000 and working in departments where there are less than 30 people employed (headCount < 30), we can achieve this easily using arrayFilters:
Let’s check the result:
As you can see, the arrayFilters allow you to modify even nested arrays easily.