2

I am new to MongoDB, and I am using mongoose for my schema. I want to update/modify a nested array from the schema, but I need help figuring out how to proceed with this.

Here is my schema :

const workoutSchema = new Schema(
  {
    dayName: {
      type: String,
      required: true
    },
    exercises: [
      {
        name: {
          type: String,
          required: true
        },
        sets: [
          {
            reps: {
              type: Number,
              required: true
            },
            weight: {
              type: Number,
              required: true
            }
          }
        ]
      }
    ]
  },
  { timestamps: true }
)

Here is the example data :

[
    {
        "_id": "6394d7b173d4d862b1124ced",
        "dayName": "Push Day",
        "exercises": [
            {
                "name": "Lat Pulldown",
                "sets": [
                    {
                        "weight": 40,
                        "_id": "6394d7db73d4d862b1124cf6"
                    },
                    {
                        "weight": 45,
                        "_id": "6394d7db73d4d862b1124cf7"
                    },
                    {
                        "weight": 45,
                        "_id": "6394d7db73d4d862b1124cf8"
                    }
                ],
                "_id": "6394d7db73d4d862b1124cf5"
            },
            {
                "name": "Deadlift",
                "sets": [
                    {
                        "reps": 5,
                        "weight": 65,
                        "_id": "6396e712ddd2681f1618922a"
                    },
                    {
                        "reps": 4,
                        "weight": 65,
                        "_id": "6396e712ddd2681f1618922b"
                    },
                    {
                        "reps": 4,
                        "weight": 65,
                        "_id": "6396e712ddd2681f1618922c"
                    }
                ],
                "_id": "6396e712ddd2681f16189229"
            }
        ],
        "createdAt": "2022-12-10T19:02:09.771Z",
        "updatedAt": "2022-12-12T08:32:17.996Z",
        "__v": 0
    }
]

exercises array can have multiple exercises. What I want is to first select the day (in this case Push Day and then add select the specific exercise (suppose Lat Pulldown in this case) and update a particular set in the exercises array. I am unable to figure out this. Can anyone point me in the right direction? Thanks for reading.

await WorkoutModel.findOneAndUpdate(
    { "exercises.sets._id": setId },
    { $set: { "exercises.$.sets": req.body } }
  )

I tried using this, but it's replacing the whole sets object rather than a single object.

2 Answers 2

2

To modify or update objects inside an array in Mongoose, you can use the Model.updateMany() method, along with the $set operator and the $positional operator. For example, if you have a model called BlogPost with a field called comments that contains an array of objects, you could use the following code to update a specific object in the array:

BlogPost.updateMany(
    { "comments._id": <id of the object to update> },
    { $set: { "comments.$.name": "New name" } }
)

In the above code, the $set operator is used to update the name field of the object in the comments array that has a matching _id field. The $ positional operator is used to specify which element in the comments array to update.

Alternatively, you can use the Model.findOneAndUpdate() method to update a single document that contains an array of objects. For example:

BlogPost.findOneAndUpdate(
    { "comments._id": <id of the object to update> },
    { $set: { "comments.$.name": "New name" } }
)

In this case, the findOneAndUpdate() method will find the first document that matches the query, and then update the specified object in the comments array. This method is useful if you only want to update a single document, rather than multiple documents as with the updateMany() method.

Sign up to request clarification or add additional context in comments.

Comments

1

You can use arrayFilters as follow:

db.collection.update({
"dayName": "Push Day",
"exercises.sets._id": "6394d7db73d4d862b1124cf6"
},
{
$set: {
 "exercises.$[y].sets.$[x]": {
  test: 1
  }
}
},
{
  arrayFilters: [
{
  "x._id": "6394d7db73d4d862b1124cf6"
 },
{
  "y.name": "Lat Pulldown"
 }
]
})

Playground

2 Comments

This works, thanks. Is there some way in which I can update only the values that I am sending while keeping the old values. Suppose I have a set { reps: 4, weight: 30} and I am updating only the {weight: 35}, but this replaces the complete object, and reps is removed. Any workaround this?
you can update values only as follow: mongoplayground.net/p/mrcwJ3H0V8H

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.