MongoDB is a document-based database, and a document is JSON-like format. Therefore, MongoDB can store various data structures. Moreover, in order to manage those documents, MongoDB provides a powerful ubiquitous language to operate documents.
Here comes a question. We usually perform CRUD on documents, however, do you know how to update the element in a list from certain documents? This article is my experiment of array operations.
The original collections is given as follows:
{ _id: ObjectId("61bb0d7cf08a56308c62110b"),
prop: [ { a: 1, b: true }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0dbaf08a56308c62110c"),
prop: [ { a: 1, b: true }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0dcaf08a56308c62110d"),
prop: [ { a: 3, b: true }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0fcef08a56308c62110e"),
prop: [ { a: 1, b: false } ] }
Update a key of elements in an array
We have an array, prop
, with elements, and those elements contains a
and b
are integer and boolean respectively. What we want to do is update b
to false
if a
is equal to 1
.
The command is: db.test.updateMany({"prop.a": 1}, {$set: {"prop.$.b": false}})
. There is a dollar sign representing the result set from filtering. So, prop.$.b
means all b
with a
is 1
.
After executing the command, the collection would be:
{ _id: ObjectId("61bb0d7cf08a56308c62110b"),
prop: [ { a: 1, b: false }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0dbaf08a56308c62110c"),
prop: [ { a: 1, b: false }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0dcaf08a56308c62110d"),
prop: [ { a: 3, b: true }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0fcef08a56308c62110e"),
prop: [ { a: 1, b: false } ] }
Remove a key of elements in an array
We can $set
a key; on the other hand, we can remove a key either. The command is like the $set
one.
db.test.updateMany({"prop.a": 1}, {$unset: {"prop.$.b": ""}})
When we want to $unset
a key, the syntax is {key: ""}
, thus, {$unset: {"prop.$.b": ""}
is as expected.
Finally, the collection would be:
{ _id: ObjectId("61bb0d7cf08a56308c62110b"),
prop: [ { a: 1 }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0dbaf08a56308c62110c"),
prop: [ { a: 1 }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0dcaf08a56308c62110d"),
prop: [ { a: 3, b: true }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0fcef08a56308c62110e"),
prop: [ { a: 1 } ] }
Remove a key of certain elements in an array
Furthermore, if we want to remove b
when b
is true
rather than all b
. How can we do?
The solution is: db.test.updateMany({"prop.a": 1}, {$unset: {"prop.$[elem].b": ""}}, {arrayFilters: [{"elem.b": true}]})
.
We are using arrayFilters
to match the specific elements and indicating those elements to the $unset
criteria. Then, the collection would become:
{ _id: ObjectId("61bb0d7cf08a56308c62110b"),
prop: [ { a: 1 }, { a: 2 } ] }
{ _id: ObjectId("61bb0dbaf08a56308c62110c"),
prop: [ { a: 1 }, { a: 2 } ] }
{ _id: ObjectId("61bb0dcaf08a56308c62110d"),
prop: [ { a: 3, b: true }, { a: 2, b: true } ] }
{ _id: ObjectId("61bb0fcef08a56308c62110e"),
prop: [ { a: 1, b: false } ] }
Although we can use filter like {a: 1, b: true}
to leverage the dollar sign operations, arrayFilters
provides more possibilities to achieve more complex user scenarios. You can try to skill it.