NodeJS + Mongoose:更新Mongoose模型上的所有字段

Jam*_*mes 12 mongoose mongodb node.js

我正在使用Node,MongoDB和Mongoose构建一个api.让我烦恼的一件事是你似乎无法一次设置多个字段:

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

但是,您似乎必须计算更新查询并在Model对象上而不是在文档对象上运行它.除非您想要分配单个属性并在最后运行save().

有没有办法在不编写Mongo查询的情况下完成此操作?

jus*_*tin 12

jsaak的答案很好,但不适用于嵌套对象.我通过搜索和设置嵌套对象详细阐述了他的答案.

我将这些函数添加到utility.js文件中

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);
}
Run Code Online (Sandbox Code Playgroud)

实施为:

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();
    ...
Run Code Online (Sandbox Code Playgroud)


Sha*_*ell 10

自从第一次提出这个问题以来,这可能已经改变了,但你可以使用set方法ike 更新Mongoose中的多个路径:

// object
doc.set({
  path  : value,
  path2 : {
    path  : value
  }
});
doc.save();
Run Code Online (Sandbox Code Playgroud)

参考


jsa*_*aak 8

根据本文档,不建议直接更新:http: //mongoosejs.com/docs/2.7.x/docs/updating-documents.html

我这样解决了:

  Book.findOne({isbn: req.params.isbn}, function (err, book){
     if (err) {
        res.send(422,'update failed');
     } else {
        //update fields
        for (var field in Book.schema.paths) {
           if ((field !== '_id') && (field !== '__v')) {
              if (req.body[field] !== undefined) {
                 book[field] = req.body[field];
              }  
           }  
        }  
        book.save();
     }
  });
Run Code Online (Sandbox Code Playgroud)


Gat*_* VP 2

为了澄清这个问题,您似乎正在获取请求参数并使用这些参数来查找更新给定文档。

有没有什么方法可以在不编写 Mongo 查询的情况下完成此任务?

显而易见的答案是使用请求中的值更新模型对象。这就是你的建议...

除非您想分配单个属性并在最后运行 save() 。

但你似乎不想这样做?听起来您想直接从 Request 对象更新 Model 对象?

如果你真的想要的话,你可以这样做。您只需循环req.params并在适当的地方设置doc值即可。

for(var i in req.params) {
  if(req.params[i] != doc[i]){
    doc[i] = req.params[i];
  }
}
Run Code Online (Sandbox Code Playgroud)

应该就是这么简单。但是,只有当模型对象上有一大堆验证代码时,您才需要执行此操作。该模型的全部要点是您不想在数据库中获取随机数据。上面的行通常会“设置”正确的值,但是您肯定需要包含围绕该简单for循环进行身份验证、授权和验证的代码。