2

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.

3
  • Did you check catching the result and check if the matching document is returned. If it is not returned - your id could be wrong. Commented Nov 26, 2014 at 3:27
  • Also please post your schema. Maybe there is a mismatch of fields. Commented Nov 26, 2014 at 4:03
  • @BatScream - just added my schema (or rather the part of it that has to do with this issue). Also, i already was checking for the "doc" portion of the callback - definitely the right document, just without the updated bit. Commented Nov 26, 2014 at 6:50

3 Answers 3

5

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);
});
Sign up to request clarification or add additional context in comments.

2 Comments

brackets and rounds seem to come from no where, are this brackets subDocs and array the rounds?
...this makes no sense to me. not liking mongoose
0

Maybe there are two things here.

First, in your sheme i recommend that you use

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

so that it is rightly defined as there can be anything.

Or the second thing that might could be missing. If the existing entry doesn't exist you have to set the option upsert :true that new entrys will also get inserted.

Model.findByIdAndUpdate('theIdOfThisObject',{$set: {'subdoc.array.0.0':newObject}}, {upsert : true},console.log);

1 Comment

Hi @Mario - neither of these are the issue. I've figured it out - you can see my answer :)
0

I had the same problem and I can confirm, this line was the fix:

doc.markModified('brackets.rounds');

Comments

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.