Vis*_*hal 12 javascript mongoose mongodb node.js
假设我有一个像这样的猫鼬模式:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var testSchema = new Schema({
name: {type: String, required: true},
nickName: {type: String}
});
var Test = module.exports = mongoose.model('Test', testSchema);
Run Code Online (Sandbox Code Playgroud)
我使用变量Test声明了CRUD操作的方法.从那一个这样的方法是更新,其定义如下:
module.exports.updateTest = function(updatedValues, callback) {
console.log(updatedValues); //this output is shown below
Test.update(
{ "_id": updatedValues.id },
{ "$set" : { "name" : updatedValues.name, "nickName" : updatedValues.nickName } },
{ multi: false },
callback
);
};
Run Code Online (Sandbox Code Playgroud)
现在,我在我的节点路由器中使用此方法,如下所示:
router.put('/:id', function(req, res, next) {
var id = req.params.id,
var name = req.body.name,
var nickName = req.body.nickName
req.checkBody("name", "Name is required").notEmpty();
var errors = req.validationErrors();
if(errors) { ........ }
else {
var testToUpdate = new Test({
_id: id,
name: name,
nickName: nickName || undefined
});
Test.updateTest(testToUpdate, function(err, result) {
if(err) { throw(err); }
else { res.status(200).json({"success": "Test updated successfully"}); }
});
}
});
Run Code Online (Sandbox Code Playgroud)
现在如果我在数据库中保存一条新记录然后在数据库中看到它,那么它看起来像:
{
"_id" : ObjectId("ns8f9yyuo32hru0fu23oh"), //some automatically generated id
"name" : "firstTest",
"__v" : 0
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我在不更改任何内容的情况下更新同一文档,那么如果我查看数据库中的相同记录,那么我得到:
{
"_id" : ObjectId("ns8f9yyuo32hru0fu23oh"), //some automatically generated id
"name" : "firstTest",
"__v" : 0,
"nickName" : null
}
Run Code Online (Sandbox Code Playgroud)
你能看到nickName被设置为null吗?我不希望它像这样工作.我希望如果我的属性为null,那么该属性不应该包含在记录中.
如果你还记得,我有控制台在更新之前记录了updatedValues.(参见第二个代码块).所以,这是记录的值:
{
"_id" : ObjectId("ns8f9yyuo32hru0fu23oh"), //some automatically generated id
"name" : "firstTest"
}
Run Code Online (Sandbox Code Playgroud)
我不知道为什么,但是nickName不存在于记录的值中,然后在更新后我得到nickName: null.我认为,问题在于第二个代码块.你能检查一下吗?
注意:
实际上,我的架构中的字段比我指定的字段多得多.某些字段也引用其他记录.
小智 8
您可以通过在 update 方法中将 runValidators 选项设置为 true 来阻止此类文档在 MongoDB 中更新。
前任:
module.exports.updateTest = function(updatedValues, callback) {
Test.update(
{ "_id": updatedValues.id },
{ "$set" : {
"name" : updatedValues.name, "nickName" : updatedValues.nickName } ,
},
{ multi: false, runValidators: true },
callback
);
};
Run Code Online (Sandbox Code Playgroud)
此外,您还可以将选项omitUndefined设置为true以防止反映未定义的值。
前任:
module.exports.updateTest = function(updatedValues, callback) {
Test.update(
{ "_id": updatedValues.id },
{ "$set" : {
"name" : updatedValues.name, "nickName" : updatedValues.nickName } ,
},
{ multi: false, runValidators: true, omitUndefined: true },
callback
);
};
Run Code Online (Sandbox Code Playgroud)
我不会这样写,但我会告诉你为什么你的代码失败了。
问题是你的 $set 块
您选择将值专门设置为传入的更新对象。如果该值是undefined您强制 mongo 将其设置为 null。
问题来了
例如,在数据库中:
{
"_id" : ObjectId("ns8f9yyuo32hru0fu23oh"),
"name" : "firstTest",
"nickname": "jack",
"__v" : 0
}
如果你通过,testToUpdate = { name: 'foo' }你最终会得到
Test.update({ ... }, { $set: { name: 'foo', nickname: undefined }}
因为你正在updatedValues.nickname摆脱争论,而那是未定义的
你想要的是什么
Test.update({ ... }, { $set: updatedValues }翻译成Test.update({ ... }, { $set: { name: 'foo' } }.
您不再提供昵称的键,因此不会将其设置为 undefined/null。
我会使用猫鼬插件而不用担心手动将字段一直传递到您的模型
见https://github.com/autolotto/mongoose-model-update
你可以定义可更新的字段,然后你就可以做
model.update(req.body) 不用担心这一切
即使您不想使用该插件,您仍然可以这样做
Test.findByIdAndUpdate(id, { name, nickname }, callback)