字段上的自定义验证,用于检查该字段是否已存在并处于活动状态

时间:2019-03-29 11:00:39

标签: node.js validation mongoose mongoose-schema

我有一个mongodb集合“用户”,其中包含“名称”,“电子邮件”和“活动”字段。 我想添加一个验证,对于每个文档电子邮件都应该是唯一的。但是,如果文档无效,即“有效”为假,则可以接受电子邮件。

这是模特

email: { type: String, validate: {
  validator: function(v) {
    return new Promise((resolve, reject)=> {
      console.log("validating email")
      const UserModel = mongoose.model('User');
      UserModel.find({email : v, active: true}, function (err, docs) 
         {
          if (!docs.length){
              resolve();
          }else{
              console.log('user exists: ',v);
              reject(new Error("User exists!"));
          }
      });
    })
  },
  message: '{VALUE} already exists!'
   }
 },
name: {
  type: String,
  required: true
 },
 active: {
   type: Boolean,
    default: true
 }

问题是每当我对此模型进行任何更新时,就会调用此验证。 因此,如果我更新名称,则也会调用此验证,并且会给出错误消息,指出电子邮件已经存在。

如何在电子邮件字段中添加验证,以便如果有人向数据库中添加新条目或更新电子邮件,则它会在数据库中检查现有用户是否具有相同的电子邮件ID并处于活动状态?

2 个答案:

答案 0 :(得分:0)

例如,如果用户已经注册了Mongo DB,我将首先调用Mongoose findOne函数;

let foundUser = await User.findOne({email});
if (!foundUser) {
 // update user, create user etc.
 ...
}

我认为最好不要在Mongoose文档对象中使用逻辑。也许有一种方法可以实现,但是我更喜欢在代码中而不是在文档中进行这些验证,这只是我的偏爱。

您还可以尝试使电子邮件具有以下独特性:

email: {
  type: String,
  unique: true
}

答案 1 :(得分:0)

我将使用unique compound index,而不是对数据库进行其他查询。您的代码如下所示:

const schema = = new Schema(...);

schema.index({email: 1, active: 1}, {unique: true});

Mongo本身会拒绝您的文档,您可以像这样在代码中捕获它:

const {MongoError} = require('mongodb'); // native driver

try {
  await model.updateOne(...).exec(); // or .save()
} catch (err) {
  //11000 is error code for unique constraints
  if (err instanceof MongoError && err.code === 11000)
    console.error('Duplicate email/active pair');
}