Chris Chris - 1 month ago 10
Javascript Question

Updating objects within array in MongoDB with mongoose

I'm trying to update objects within an array in a document. The objects are not subdocuments and therefore don't have a unique ID. I've tried looking at various methods to do this but it just doesn't seem to have any effect (as in, nothing happens - no errors, but the document doesn't update.

Probably easier just to show the code. First, here's an example of a document in this collection:

{
_id: 123,
//other fields go here
submissions: [
{
submission: 1,
downloaded: null, //This should be an ISODate when populated
assessor: null, //This should be an ObjectID when populated
feedbackUploaded: null, //This should also be an ISODate
path: '401Test1.doc',
assessorNotes: null //This should be a string when populated
},
{
submission: 2,
downloaded: null,
assessor: null,
feedbackUploaded: null,
path: '401Test2.doc',
assessorNotes: null
}
]
}


And now my mongoose query (within an express route):

const unit = req.body.unit; //e.g. 123
const submission = req.body.submission // e.g. 2
const date = Date.now();

Unit.update({ "_id": unit, "submissions.submission": submission }, {
$set: {
'submissions.assessorNotes': req.body.assessorComments,
'submissions.feedbackUploaded': date,
'submissions.assessor': req.body.assessor
}, function(err){
//callback
}
})


I've also tried this using
$
notation in the
$set
command i.e.
'submissions.$.assessorNotes': req.body.assessorComments'
but this doesn't seem to work either.

Where am I going wrong?!

Cheers!

Chris

Answer

Just tested this with the positional operator as mentioned above by TomG in a shell.

> db.foo.find().pretty()
{
    "_id" : 123,
    "submissions" : [
        {
            "submission" : 1,
            "downloaded" : null,
            "assessor" : null,
            "feedbackUploaded" : null,
            "path" : "401Test1.doc",
            "assessorNotes" : null
        },
        {
            "submission" : 2,
            "downloaded" : null,
            "assessor" : null,
            "feedbackUploaded" : null,
            "path" : "401Test2.doc",
            "assessorNotes" : null
        }
    ]
}

Then I ran the update command:

db.foo.update(
  { _id: 123, "submissions.submission": 2 }, 
  { $set: {
    "submissions.$.assessorNotes": "testAssessorNotes",
    "submissions.$.feedbackUploaded": new Date(),
    "submissions.$.assessor": "testAssessor"
  } }
)

Results are as follows:

{
    "_id" : 123,
    "submissions" : [
        {
            "submission" : 1,
            "downloaded" : null,
            "assessor" : null,
            "feedbackUploaded" : null,
            "path" : "401Test1.doc",
            "assessorNotes" : null
        },
        {
            "submission" : 2,
            "downloaded" : null,
            "assessor" : "testAssessor",
            "feedbackUploaded" : ISODate("2016-10-26T15:33:09.573Z"),
            "path" : "401Test2.doc",
            "assessorNotes" : "testAssessorNotes"
        }
    ]
}

Edit: My hunch is that the error could also be with the update in Mongoose, you could try changing both to the positional operators, as well as using findOneAndUpdate if it fits your needs instead of update.

Please try this query for Mongoose:

Unit.update(
    { "_id": unit, "submissions.submission": submission }, 
    { $set: {
        'submissions.$.assessorNotes': req.body.assessorComments,
        'submissions.$.feedbackUploaded': date,
        'submissions.$.assessor': req.body.assessor
    } }, function(err, result) {
        //callback
    }
});
Comments