猫鼬自定义验证几个字段在更新
Mongoose custom validation of several fields on update
首先,这没有帮助。
假设我们有一个用户模型:
const schema = new mongoose.Schema({
active: { type: Boolean },
avatar: { type: String }
});
const User = mongoose.model('User', schema);
当我们更新它(设置头像):
// This should pass validation
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
我们希望根据当前(或更改的)active
属性值验证它。
案例# 1
-
active
即false
- 我们不应该能够设置头像-它不应该通过验证
案例# 2
-
active
即true
- 我们应该能够设置头像-它应该通过验证
想法/h3>- 使用自定义验证器
const schema = new mongoose.Schema({
active: { type: Boolean },
avatar: { type: String, validate: [validateAvatar, 'User is not active'] }
});
function validateAvatar (value) {
console.log(value); // user.avatar
console.log(this.active); // undefined
}
const schema = new mongoose.Schema({
active: { type: Boolean },
avatar: { type: String, validate: [validateAvatar, 'User is not active'] }
});
function validateAvatar (value) {
console.log(value); // user.avatar
console.log(this.active); // undefined
}
所以这将不起作用,因为我们没有访问active
字段的权限。
- 使用预"validate"钩子
schema.pre('validate', function (next) {
// this will never be called
});
这个钩子不能用update
方法。
- 使用预"update"钩子
schema.pre('update', function (next) {
console.log(this.active); // undefined
});
这对我们不起作用,因为它没有访问模型字段的权限。
- 使用post "update"钩子
schema.post('update', function (next) {
console.log(this.active); // false
});
这个可以工作,但就验证而言不是很好的选择,因为只有当模型已经保存时才调用该函数。
问题
所以有一种方法来验证基于几个字段的模型(既保存在DB和新的)保存它之前,而使用model.update()
方法?
作为总结:
- 初始用户对象
{ active: false, avatar: null }
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
- 验证应该有权访问
{ active: false, avatar: 'user1.png' }
- 如果验证失败,更改不应该传递给DB
由于使用update()
的限制,我决定这样解决问题:
- 使用自定义验证器(问题中提到的想法#1)
- 不要使用
update()
所以不用
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
我使用
User.findOne({ _id: id })
.then((user) => {
user.avatar = 'user1.png';
user.save();
});
在本例中,自定义验证器按预期工作。
注:我选择这个答案作为我的正确答案,但我将奖励最相关的答案。
您可以使用mongoose文档中指定的上下文选项来完成此操作。
上下文选项允许您在更新验证器中设置此值到底层查询。
在你的代码中你可以像这样在路径上定义你的
validator
:
function validateAvatar (value) {
// When running update validators with the `context` option set to
// 'query', `this` refers to the query object.
return this.getUpdate().$set.active;
}
schema.path('avatar').validate(validateAvatar, 'User is not active');
更新时需要输入两个选项runValidators
和context
。所以你的更新查询变成:
var opts = { runValidators: true, context: 'query' };
user.update({ _id: id }, { $set: { avatar: 'user1.png' }, opts });
您是否尝试给active一个默认值,以便它不会在mongodb中未定义
const schema = new mongoose.Schema({
active: { type: Boolean, 'default': false },
avatar: { type: String,
trim: true,
'default': '',
validate: [validateAvatar, 'User is not active']
}});
function validateAvatar (value) {
console.log(value); // user.avatar
console.log(this.active); // undefined
}
当你创建用户时,你是否这样设置用户
var User = mongoose.model('User');
var user_1 = new User({ active: false, avatar: ''});
user_1.save(function (err) {
if (err) {
return res.status(400).send({message: 'err'});
}
res.json(user_1);
});
你可以尝试使用预"save"钩子。我以前使用过它,可以在"this"中获得值。
schema.pre('save', function (next) {
console.log(this.active);
});
希望这对你也有用!
您必须使用异步自定义验证器:
const schema = new mongoose.Schema({
active: { type: Boolean },
avatar: {
type : String,
validate : {
validator : validateAvatar,
message : 'User is not active'
}
}
});
function validateAvatar(v, cb) {
this.model.findOne({ _id : this.getQuery()._id }).then(user => {
if (user && ! user.active) {
return cb(false);
} else {
cb();
}
});
}
(并将runValidators
和context
选项传递给update()
,正如Naeem的回答所建议的那样)。
但是,每次更新都需要一个额外的查询,这是不理想的。
作为一种替代方案,您还可以考虑使用如下内容(如果无法更新非活动用户的约束比实际验证更重要):
user.update({ _id : id, active : true }, { ... }, ...);
相关文章:
- jQuery Wan Spinner插件的多个字段
- Angular ng repeat order将多个字段作为一个字段
- Dynamics CRM 2016:自动完成多个字段
- 更新嵌套对象的多个字段
- 使用单个文本框向多个字段添加严格搜索
- 当出现多个字段时,jquery时间条目问题
- 使用数组表示法对多个字段执行jQuery日期选择器
- 如何使用2个字段名称作为筛选器
- 如何使用jquery将两个字段组合为下拉菜单中的选项
- 如何防止某些形式's个字段无法提交
- Angularjs 通过选择不同选择框中的两个字段来填充选择框
- 如何在一个表单标记中验证多个字段集
- 使用Join,要求两个字段中的一个字段为非空
- 在原始对象的基础上创建新对象的最简单方法,但没有几个字段
- jQuery在几个字段中倒计时
- 在mongoose express中选择几个字段作为数组
- Rivets.js属性依赖于几个字段
- Rails:如何编写一个测试,以确保几个字段在关闭时隐藏,但在打开时显示,并且具有正确的值
- 猫鼬自定义验证几个字段在更新
- 使用Javascript显示和隐藏几个字段