NilsH NilsH - 1 month ago 19
Node.js Question

Partial update of a subdocument with nodejs/mongoose

Is it possible to set multiple properties on a (sub)document in one go with Mongoose? An example of what I'm trying to do:

Let's say I have this schema:

var subSchema = new Schema({
someField: String,
someOtherField: String
});

var parentSchema = new Schema({
fieldOne: String,
subDocs: [subSchema]
})


Then I would like to do:

exports.updateMyDocument = function(req, res) {
var parentDoc = req.parentDoc; // The parent document. Set by parameter resolver.
var document = req.myDoc; // Sub document of parent. Set by parameter resolver.
var partialUpdate = req.body; // updated fields sent as json and parsed by body parser
// I know that the statement below doesn't work, it's just an example of what I would like to do.
// Updating only the fields supplied in "partialUpdate" on the document
document.update(partialUpdate);
parentDoc.save(function(err) {
if(err) {
res.send(500);
return;
}
res.send(204);
});
};


Normally, I could achieve this using the
$set
operator, but my problem is that
document
in this example is a subdocument (embedded schema) of
parentDoc
. So when I tried to do

Parent.update({_id: parentDoc._id, "subDocs._id": document._id},
{$set: {"subDocs.$" : partialUpdate}},
function(err, numAffected) {});


it replaced the subdocument instance identified by
subDocs._id
. Currently I have "solved" it by setting only fields manually, but I was hoping for a better way to do this.

Answer

Build up a $set object programmatically based on the fields of partialUpdate to update just those fields using dot notation:

var set = {};
for (var field in partialUpdate) {
  set['subDocs.$.' + field] = partialUpdate[field];
}
Parent.update({_id: parentDoc._id, "subDocs._id": document._id}, 
    {$set: set}, 
    function(err, numAffected) {});