Search code examples
node.jsmongodbmongoosemongodb-querynode-mongodb-native

MongoDB not updating subdocument within double-nested array (using Mongoose FindByIdAndUpdate) - EXACT POSITION KNOWN


I have a document structure that's roughly similar to the following:

{
    "_id": "theIdOfThisObject",
    "subdoc": {
        "array": [
            [
                {
                    "parameters": {},
                    "winner": null,
                    "participants": [
                        "Person1",
                        "Person2"
                    ]
                },
                {
                    "parameters": {},
                    "winner": null,
                    "participants": [
                        "Person3",
                        "Person4"
                    ]
                }
            ],
            []
        ]
    },
}

I am entirely trying to replace one of the subdocuments within the nested array. I do not need to search for it - i know the exact position.

For example, I am trying to replace the first subdocument with

                    "parameters": {"frog":20},
                    "winner": "Person1",
                    "participants": [
                        "Person1",
                        "Person2"
                    ]

which we'll say is saved as an object called newObject.

I expect the following code to work (and Model is a real Mongoose Model):

Model.findByIdAndUpdate('theIdOfThisObject',{$set: {'subdoc.array.0.0':newObject}}, function(err,doc){
  console.log('doc is returned, but nothing is updated')
});

I have no idea what is going on and why this isn't working. Does anybody have any suggestions? I have been using MongoDB's native node driver for a very long time (3 years), but Mongoose is fairly new to me.

EDIT - adding schema as per comment request

The schema is pretty straightforward. looks as follows:

var Schema   = new mongoose.Schema({
    subdoc: {
        array: [{}]
    }
});

There's other fields in there, but this is the only one that matters in this case. My understanding is that having the Schema have a [{}] means that there will be an array of any kind of JSON arrangement. The Schema also lets me initially set the subdocument in question - it just doesn't let me update it for whatever reason.


Solution

  • I have figured out the issue. Apparently when using the Mixed Schema type, (which is the same as {}) with Mongoose, updating a subfield within the object is a 2 step process. You can't just use findByIdAndUpdate().

    You must first use fineById(), grab the document in the callback, run markModified() on the document in question (passing in the path to the subdocument), and then finally save said document. Here's the code:

    Model.findById('theIdOfThisObject', function(err,doc){
            //update the proper subdocument
            doc.subdoc.array[0][0] = newObject;
            //then mark it as modified and save it
            doc.markModified('brackets.rounds');
            //save the model
            doc.save(callback);
    });