繁体   English   中英

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

[英]NodeJS + Mongoose: Updating all fields on a Mongoose model

我正在使用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();
...

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

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

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);
}

实施为:

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();
    ...

自从这个问题首次被问到以来,这可能已经发生了变化,但您可以使用set方法ike更新Mongoose中的多个路径:

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

参考

根据本文档,不建议直接更新: 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();
     }
  });

如果要更新整个文档,可以根据其ID删除文档并再次存储整个对象。 该对象必须包含mongo文档的每个字段的数据。

这是一个例子。

 mongoDBCollectionObject.findOneAndRemove({ // -- it will delete the entire document _id: req.body.fieldsdata._id // here fiedsdata is exact copy with modification of previous data }, function(err, data) { var newFieldsData = new mongoDBCollectionObject(fieldsdata); //-- fieldsdata updated data newFieldsData.save(function(err, data) { // save document to that collection with updated data if (err) { console.log(err); } else res.json({ success: true }); }); }) 

为了澄清这个问题,看起来您正在使用Request参数并使用它们来查找更新给定文档。

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

显而易见的答案是使用Request中的值更新Model对象。 这是你的建议......

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

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

如果你真的想要,你可以这样做。 您只需遍历req.params并在适当的位置设置doc值。

for(var i in req.params) {
  if(req.params[i] != doc[i]){
    doc[i] = req.params[i];
  }
}

应该这么简单。 但是,如果在Model对象上有大量验证代码,则只需执行此操作。 模型的重点是您不希望在DB中获取随机数据。 上面的行通常会“设置”正确的值,但您肯定需要包含用于围绕该简单for循环的身份验证,授权和验证的代码。

尝试更新没有find的集合,就像这样

Record.update({_id:req.params.id}, {$set: { field: request.field }}, {upsert: true}, function(err{...})

如果不存在,选项upsert将创建文档。

如果您有一个新对象并想要更新数据库中的整个对象,您可以一次更新多个字段,如下所示:

  1. 找到对象
  2. 获取所有架构路径(字段)
  3. 保存新对象。

 SomeModel.findOne({ 'id': 'yourid' },function (err, oldObject) { if (err) return handleError(err); // get all schema paths (fields) SomeModel.schema.eachPath(function(path) { // leave __id and __v alone if (path != '_id' && path != '__v') { // update the data from new object oldObject[path] = newObject[path]; } }) oldObject.save(function(err) { if (err) console.log(err) }); }) 

一个干净整洁的方法是使用async awaitfindOneAndRemove以及create这里是示例代码

try {
            let resp = await this.findOneAndRemove({ _id: req.body._id });
            let entry = await this.create(req.body);

    } catch (err) {

    }

不要忘记将整个函数标记为 async

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM