我有一个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并处于活动状态?
答案 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');
}