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

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

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查询?

       

网上收集的解决方案 "NodeJS + Mongoose:更新Mongoose模型的所有字段"

jsaak的答案是好的,但不适用于嵌套的对象。 我通过search和设置嵌套对象来阐述他的答案。

我将这些函数添加到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(); ... 

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

也许这是第一次问这个问题,但你可以使用set方法ike更新Mongoose中的多个path:

 // object doc.set({ path : value, path2 : { path : value } }); doc.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对象。 这是你build议的…

除非你想分配单独的属性,并在最后运行save()。

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

你可以做到这一点,如果你真的想要。 您只需循环req.params并在适当的位置设置doc值。

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

它应该像这样简单。 但是,如果在Model对象上有大量validation代码, 则只需要执行此操作。 整个模型的意义在于你不想在数据库中获得随机数据。 上面的行一般会“设置”正确的值,但是您肯定需要在这个简单的for循环中包含用于身份validation,授权和validation的代码。

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

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

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

如果你有一个新的对象,并想更新数据库中的整个对象,你可以像这样一次更新多个字段:

  1. find对象
  2. 获取所有模式path(字段)
  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) }); })