首先,this没有帮助。
让我们说,我们有一个用户模型:
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
属性值对其进行验证。
active
是false
active
是true
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
字段,因此无效。
schema.pre('validate', function (next) {
// this will never be called
});
此挂钩不适用于update
方法。
schema.pre('update', function (next) {
console.log(this.active); // undefined
});
这对我们无效,因为它无法访问模型字段。
schema.post('update', function (next) {
console.log(this.active); // false
});
这个有效,但在验证方面不是很好的选择,因为只有在模型已经保存时才会调用该函数。
在使用model.update()
方法时,有没有办法在保存之前根据几个字段(保存在DB和新的字段中)验证模型?
总结:
{ active: false, avatar: null }
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
{ active: false, avatar: 'user1.png' }
答案 0 :(得分:3)
由于使用update()
的限制,我决定以这种方式解决问题:
update()
所以而不是
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
我用
User.findOne({ _id: id })
.then((user) => {
user.avatar = 'user1.png';
user.save();
});
在这种情况下,自定义验证程序按预期工作。
P.S。我选择这个答案对我来说是正确的,但我会给予最相关答案的赏金。
答案 1 :(得分:1)
您可以使用unordered-containers
中指定的上下文选项执行此操作。
上下文选项
上下文选项允许您在更新验证程序中设置此值 到底层查询。
<小时/> 因此,在您的代码中,您可以在路径上定义
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 });
答案 2 :(得分:1)
您是否尝试过激活默认值,以便在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);
});
答案 3 :(得分:0)
你可以尝试使用pre&#34; save&#34;钩。我之前用过它,可以在&#34;这个&#34;中获得价值。
schema.pre('save', function (next) {
console.log(this.active);
});
希望这也适合你!
答案 4 :(得分:0)
您必须使用asynchronous custom validator:
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();
}
});
}
(并按照Naeem的回答中的建议,将runValidators
和context
选项传递给update()
。
但是,这需要对每次更新进行额外查询,这不是理想的。
作为替代方案,您也可以考虑使用类似的东西(如果无法更新非活动用户的约束比实际验证它更重要):
user.update({ _id : id, active : true }, { ... }, ...);