Array Operation in MongoDB
Tags: mongodb, database, javascript, tutorial
Published: 2022-01-17 01:10:55

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:

```json
{ _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:
```json
{ _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:
```json
{ _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:
```json
{ _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.