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查询?
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文档。
如果你有一个新的对象,并想更新数据库中的整个对象,你可以像这样一次更新多个字段:
- find对象
- 获取所有模式path(字段)
- 保存新的对象。
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) }); })