![](/img/trans.png)
[英]MongoDB/Mongoose: updating two different fields in Mongoose model
[英]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将创建文档。
如果您有一个新对象并想要更新数据库中的整个对象,您可以一次更新多个字段,如下所示:
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
await
和findOneAndRemove
以及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.