在更新时对几个字段进行Mongoose自定义验证

Naz*_*zar 6 javascript validation mongoose mongodb node.js

首先,没有帮助.

比方说,我们有一个用户模型:

const schema = new mongoose.Schema({
    active: { type: Boolean },
    avatar: { type: String }
});

const User = mongoose.model('User', schema);
Run Code Online (Sandbox Code Playgroud)

当我们更新它(设置一个头像):

// This should pass validation
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
Run Code Online (Sandbox Code Playgroud)

我们希望根据当前(或更改的)active属性值对其进行验证.

情况1

  • activefalse
  • 我们应该设置头像 - 它不应该通过验证

案例#2

  • activetrue
  • 我们应该能够设置头像 - 它应该通过验证

思路

  1. 使用自定义验证器
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
}
Run Code Online (Sandbox Code Playgroud)

所以这不起作用,因为我们没有访问active字段.

  1. 使用预"验证"钩子
schema.pre('validate', function (next) {
    // this will never be called
});
Run Code Online (Sandbox Code Playgroud)

此挂钩不适用于update方法.

  1. 使用pre"update"挂钩
schema.pre('update', function (next) {
    console.log(this.active); // undefined
});
Run Code Online (Sandbox Code Playgroud)

这对我们不起作用,因为它无法访问模型字段.

  1. 使用post"update"hook
schema.post('update', function (next) {
    console.log(this.active); // false
});
Run Code Online (Sandbox Code Playgroud)

这个可行,但在验证方面不是很好的选择,因为只有在模型已经保存时才调用该函数.

那么有什么方法可以在保存之前基于几个字段(保存在DB和新的字段中)验证模型,同时使用model.update()方法?

作为总结:

  1. 初始用户对象
{ active: false, avatar: null }
Run Code Online (Sandbox Code Playgroud)
  1. 更新
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
Run Code Online (Sandbox Code Playgroud)
  1. 验证应该有权访问
{ active: false, avatar: 'user1.png' }
Run Code Online (Sandbox Code Playgroud)
  1. 如果验证失败,则不应将更改传递给DB

Naz*_*zar 4

由于工作的限制,update()我决定这样解决问题:

  • 使用自定义验证器(问题中提到的想法#1)
  • 不要使用update()

所以而不是

User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
Run Code Online (Sandbox Code Playgroud)

我用

User.findOne({ _id: id })
    .then((user) => {
        user.avatar = 'user1.png';
        user.save();
    });
Run Code Online (Sandbox Code Playgroud)

在这种情况下,自定义验证器按预期工作。

PS 我选择这个答案对我来说是正确的,但我会给最相关的答案奖励。