我有这段代码
var ClientSchema = new Schema({
name: {type: String, required: true, trim: true}
});
var Client = mongoose.mode('Client', ClientSchema);
使用express,我使用此代码创建一个新客户端
var client = new Client(req.body);
client.save(function(err, data) {
....
});
如果我在表单上留下名称字段为空,则mongoose不允许创建客户端,因为我在架构上按需要设置它。另外,如果我在名称前后留空格,mongoose会在保存前删除该空格。
现在,我尝试使用此代码更新客户端
var id = req.params.id;
var client = req.body;
Client.update({_id: id}, client, function(err) {
....
});
它允许我更改名称,但如果我在表单上将其留空,则mongoose不会验证并保存一个空名称。如果我在名称前后添加空格,则用空格保存名称。
为什么mongoose会在保存时验证,但不会在更新时验证?我是以错误的方式做到的?
mongodb:2.4.0 猫鼬:3.6.0 表达:3.1.0 节点:0.10.1
答案 0 :(得分:68)
从Mongoose 4.0起,update()
can run validators和findOneAndUpdate()
使用新标记runValidators: true
。{/ p>
Mongoose 4.0引入了一个在
update()
和findOneAndUpdate()
上运行验证器的选项update()
来电。启用此选项将运行验证程序 对于$set
来电尝试$unset
或var ClientSchema = new Schema({ name: {type: String, required: true, trim: true} }); var Client = mongoose.model('Client', ClientSchema);
的所有字段。
例如,给定OP的Schema:
var id = req.params.id;
var client = req.body;
Client.update({_id: id}, client, { runValidators: true }, function(err) {
....
});
在每次更新时传递标记
你可以使用这样的新标志:
pre
使用pre
挂钩
如果您不想在每次更新内容时设置标记,可以为findOneAndUpdate()
设置// Pre hook for `findOneAndUpdate`
ClientSchema.pre('findOneAndUpdate', function(next) {
this.options.runValidators = true;
next();
});
挂钩:
update()
然后你可以runValidators
使用验证器,而不是每次都传递{{1}}标志。
答案 1 :(得分:54)
你没有做错任何事,validation
被实现为Mongoose中的内部中间件,而中间件在update
期间没有被执行,因为它基本上是本机驱动程序的传递。 / p>
如果您希望验证客户端更新,则需要find
要更新的对象,将新属性值应用于它(请参阅下划线的extend
方法),然后调用{{1}在它上面。
Mongoose 4.0更新
正如评论和victorkohl的回答中所述,当您在save
中添加$set
选项时,Mongoose现在支持验证$unset
和runValidators: true
运算符的字段调用
答案 2 :(得分:2)
mongodb默认情况下不对更新运行验证。 为了在默认情况下也使更新时的验证生效,就在连接到mongodb之前,您只能设置全局设置,例如:
mongoose.set('runValidators', true); // here is your global setting
mongoose.connect(config.database, { useNewUrlParser: true });
mongoose.connection.once('open', () => {
console.log('Connection has been made, start making fireworks...');
}).on('error', function (error) {
console.log('Connection error:', error);
});
,任何内置或自定义验证也将在更新时运行
答案 3 :(得分:0)
在你的模特中,例如Category.js文件:
const CategorySchema = mongoose.Schema({
category_name : {
type : String,
required : [true, 'Category Name Is Required !'],
trim : true,
maxlength : [30, 'Category Name Is To Long !'],
unique : true,
});
const Category = module.exports = mongoose.model("Category",CategorySchema);
在你的路线档案中:
router.put("/",(req,res,next)=>{
Category.findOneAndUpdate(
{_id : req.body.categoryId},
{$set : {category_name : req.body.category_name} },
**{runValidators: true}**, function(err,result) {
if(err){
if(err.code === 11000){
var duplicateValue = err.message.match(/".*"/);
res.status(200).json({"defaultError":duplicateValue[0]+" Is Already Exsist !"});
}else{
res.status(200).json({"error":err.message} || {"defaultError":'Error But Not Understood !'});
}
}else{
console.log("From category.js (Route File) = "+result);
res.status(200).json({"success":"Category Updated Successfully!!"});
}
});
答案 4 :(得分:0)
exports.updateGroup = (request, response, next) => {
const requestObj = request.body;
var conditions = {
_id: request.body._id,
communityId: request.body.communityId
};
var newValues = {
$set: requestObj
};
Group.updateOne(conditions, newValues, { ***runValidators: true*** }, (err, group) => {
if (err) return response.json({
message: "Updation of group failed",
error: err,
status: 500
});
response.json(group);
});
};
您需要添加{runValidators:true}作为用于进行更新的验证的第三个参数。
答案 5 :(得分:0)
如果您在猫鼬的配置中添加此选项,它将起作用:
mongoose.set('runValidators',true)
答案 6 :(得分:0)
您可以通过设置选项 runValidators: true
在更新时运行验证。
const Kitten = db.model('Kitten', kittenSchema);
const update = { color: 'blue' };
const opts = { runValidators: true };
Kitten.updateOne({}, update, opts, function() {
// code
});
const Kitten = db.model('Kitten', kittenSchema);
const update = { color: 'blue' };
const opts = { runValidators: true };
Kitten.updateOne(
{
_id: req.params.id
},
{
$set: { ...update },
},
opts
).then(result => {
// code
})
阅读更多:https://mongoosejs.com/docs/validation.html#update-validators