Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS + Mongoose: Updating all fields on a Mongoose model

I'm building out an api using Node, MongoDB and Mongoose. One thing that is bugging me is that you can't seem to set multiple fields at once:

app.put('/record/:id', function(req, res) {
  Record.findById(req.params.id, function(err, doc) {
    if (!err) {
      doc.update(req.params);
      doc.save();
...

However, it seems that you have to work out the update query and run it on the Model object rather than on the document object. Unless you want to assign individual properties and run save() at the end.

Is there any way of accomplishing this without having to write a Mongo query?

like image 401
James Avatar asked Feb 20 '12 23:02

James


People also ask

How can I update multiple documents in Mongoose?

You can update multiple documents using the collection. updateMany() method. The updateMany() method accepts a filter document and an update document. If the query matches documents in the collection, the method applies the updates from the update document to fields and values of the matching documents.

How do I update my Mongoose?

The save() function is generally the right way to update a document with Mongoose. With save() , you get full validation and middleware. For cases when save() isn't flexible enough, Mongoose lets you create your own MongoDB updates with casting, middleware, and limited validation.

Which update method is valid if we want to update single document in Mongoose model?

Mongoose | update() Function The update() function is used to update one document in the database without returning it.

Why we use $set in Mongoose?

In the doc, it mentioned that: By default, if you don't include any update operators in doc, Mongoose will wrap doc in $set for you. This prevents you from accidentally overwriting the document.


2 Answers

jsaak's answer is good but doesn't work for nested objects. I elaborated on his answer by searching and setting nested objects.

I added these functions to a utility.js file

var _ = require('underscore');

exports.updateDocument = function(doc, SchemaTarget, data) {
    for (var field in SchemaTarget.schema.paths) {
       if ((field !== '_id') && (field !== '__v')) {
            var newValue = getObjValue(field, data);
            console.log('data[' + field + '] = ' + newValue);
            if (newValue !== undefined) {
                setObjValue(field, doc, newValue);
          }  
       }  
    }
    return doc;
};

function getObjValue(field, data) {
    return _.reduce(field.split("."), function(obj, f) { 
        if(obj) return obj[f];
    }, data);
}

function setObjValue(field, data, value) {
  var fieldArr = field.split('.');
  return _.reduce(fieldArr, function(o, f, i) {
     if(i == fieldArr.length-1) {
          o[f] = value;
     } else {
          if(!o[f]) o[f] = {};
     }
     return o[f];
  }, data);
}

implement as:

var util = require('./utility');

app.put('/record/:id', function(req, res) {
  Record.findById(req.params.id, function(err, doc) {
    if (!err) {
      utils.updateDocument(doc, Record, req.params);
      doc.save();
    ...
like image 161
justin Avatar answered Oct 26 '22 04:10

justin


Maybe this has changed since this question was first asked, but you can update multiple paths in Mongoose with the set method ike:

// object
doc.set({
  path  : value,
  path2 : {
    path  : value
  }
});
doc.save();

References

  • http://mongoosejs.com/docs/api.html#document_Document-set
like image 42
Shane Stillwell Avatar answered Oct 26 '22 05:10

Shane Stillwell