How to Update Deeply Nested Array in MongoDB/ Mongoose ?

In MongoDB/Mongoose, updating deeply nested arrays can be challenging due to the nested structure. This article will explore various approaches to update deeply nested arrays efficiently using both MongoDB queries and Mongoose methods.

Explaining each approach one by one below:

Table of Content

  • Using MongoDB’s Update Operators
  • Using Mongoose’s findByIdAndUpdate Method with $ positional operator
  • Using Mongoose’s findOneAndUpdate Method with arrayFilters

Using MongoDB’s Update Operators

This approach utilizes MongoDB’s update operators along with arrayFilters to specify the conditions for updating deeply nested arrays.

db.collection.update(
{ <query> },
{ $set: { "nestedArray.$[outer].innerArray.$[inner].field": value } },
{ arrayFilters: [{ "outer._id": <outerId> }, { "inner._id": <innerId> }] }
);

Using Mongoose’s findByIdAndUpdate Method with $ positional operator

In this approach, we use Mongoose’s findByIdAndUpdate method along with the $ positional operator to update the deeply nested arrays.

Model.findByIdAndUpdate(
parentId,
{ $set: { "nestedArray.$[outer].innerArray.$[inner].field": value } },
{ arrayFilters: [{ "outer._id": outerId }, { "inner._id": innerId }], new: true }
);

Using Mongoose’s findOneAndUpdate Method with arrayFilters

Similar to Approach 2, this approach uses Mongoose’s findOneAndUpdate method with arrayFilters to update deeply nested arrays.

Model.findOneAndUpdate(
{ _id: parentId },
{ $set: { "nestedArray.$[outer].innerArray.$[inner].field": value } },
{ arrayFilters: [{ "outer._id": outerId }, { "inner._id": innerId }], new: true }
);

Steps to Create Application (Install Required Modules):

  • Install MongoDB and Mongoose.
  • Set up a Node.js project with npm init.
  • Install required packages:
npm install mongoose

package.json:

"dependencies": {
"mongoose": "^6.1.4"
}

Example: Below is the basic code example:

Node
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mydatabase', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});
const db = mongoose.connection;

const ChildSchema = new mongoose.Schema({
  name: String,
  value: Number
});

const ParentSchema = new mongoose.Schema({
  nestedArray: [{
    outerName: String,
    innerArray: [ChildSchema]
  }]
});

const ParentModel = mongoose.model('Parent', ParentSchema);

async function updateNestedArray(parentId, outerId, innerId, newValue) {
  try {
    const updatedParent = await ParentModel.findOneAndUpdate(
      { _id: parentId },
      { $set: { "nestedArray.$[outer].innerArray.$[inner].value": newValue } },
      { 
        arrayFilters: [{ "outer._id": outerId }, { "inner._id": innerId }],
        new: true
      }
    );
    console.log("Updated Parent:", updatedParent);
  } catch (error) {
    console.error("Error updating nested array:", error);
  }
}

const parentId = "60a3c08462f7f2085c0a1f6b";
const outerId = "60a3c08462f7f2085c0a1f6c";
const innerId = "60a3c08462f7f2085c0a1f6d";
const newValue = 100;

updateNestedArray(parentId, outerId, innerId, newValue);

Output:

Updated Parent: {
_id: ObjectId("60a3c08462f7f2085c0a1f6b"),
nestedArray: [
{
outerName: "Outer Object",
_id: ObjectId("60a3c08462f7f2085c0a1f6c"),
innerArray: [
{
name: "Inner Object",
_id: ObjectId("60a3c08462f7f2085c0a1f6d"),
value: 100 // Updated value
}
]
}
]
}