0

Original:

_id: "54022f8b705ebb4010170f02",
exercises: [
{
    name: "Bench"
},
date: "2014-08-30T20:31:22.982Z"

Desired update:

_id: "54022f8b705ebb4010170f02",
exercises: [
{
    name: "Bench",
    sets: [{weight: 275, reps: 5}]
},
date: "2014-08-30T20:31:22.982Z"

I have tried stuff along the lines of this (doesn't work), but am having trouble getting a set into the right spot:

 db.workouts.update(
       { _id: ObjectId('54022f8b705ebb4010170f02'), "exercises.name":'Bench'},
       {
          $push: 
          { 
              sets: 
              {
                  weight: 275,
                  reps: 5,
              }
          }
       }
    )

Also, happily taking suggestions if there's a better way to model this.

1 Answer 1

1

Push operations should be fine here, but what you need to do is identify the array position where you are going to push the object to. You had half of the update done by looking for "Bench" in the query portion. Now you need to identify with the positional $ operator and also realize that "sets" is an element under "exercises", so it needs to be notated that way:

db.workouts.update(
    { 
        "_id": ObjectId("54022f8b705ebb4010170f02"), 
        "exercises.name":"Bench"
    },
    {
        "$push": {
            "exercises.$.sets": {
                 "weight": 275,
                 "reps": 5
             }
        }
    }
)

So that said, using $push to add new "sets" items or additional "sets" items is not a problem, so if your model is basically "append only" then this is fine. The only problem you would have is if you intended to "update" that inner array element in a certain position that was not known. For example change the element with "weight" 275 to 6 "reps".

That problem occurs because the positional $ operator used only captures the "first" matched position of the array, and it is always the "outer" array or "exercises". So you cannot do this:

db.workouts.update(
    { 
        "_id": ObjectId("54022f8b705ebb4010170f02"), 
        "exercises.sets.weight": 275
    },
    {
        "$set": {
            "exercises.$.sets.$.weight": 285
        }
    }
)

But for a known position you can:

db.workouts.update(
    { 
        "_id": ObjectId("54022f8b705ebb4010170f02"), 
        "exercises.sets.weight": 275
    },
    {
        "$set": {
            "exercises.$.sets.0.weight": 285
        }
    }
)

But the "first" array position is always the index that is returned and not from the inner array.

That is the main thing to be aware of when considering using nested arrays in your modelling.

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

1 Comment

Amazing. I love MongoDB.

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.