我正在尝试确定如何对Mongoose模式进行异步验证 - 特别是在这种情况下是用户名。 TMK,为了确保用户名是唯一的,我们必须手动查询数据库以查看是否已存在相同的用户名。这是一个异步查询。然而,进行验证的方法是:'每个模式项的属性,似乎要求同步验证功能。换句话说,这一行:
验证:[validation.usernameValidator,'不是有效的用户名']
似乎要求usernameValidator是同步的,问题是我需要它是异步的,原因如上所述。
所以,我有一个类似于用户的Mongoose模式:
var validation = {
usernameValidator: function (candidate) {
return true;
},
passwordValidator: function (candidate) {
return true;
}
};
userSchema = mongoose.Schema({
username: {
type: String,
isUnique: true,
required: true,
validate: [validation.usernameValidator, 'not a valid username']
},
passwordHash: {
type: String,
required: true,
validate: [validation.passwordValidator, 'not a valid password']
},
email: {
type: String,
isUnique: true,
required: true,
validate: [validation.emailValidator, 'not a valid email address']
}
});
userSchema.pre('save', function (next) {
var self = this;
if (!self.isModified('passwordHash')) {
return next();
}
bcrypt.hash(self.passwordPreHash, SALT_WORK_FACTOR, function (err, hash) {
if (err) {
return next(err);
}
else if(hash == null){
return next(new Error('null/undefined hash'));
}
else {
self.passwordHash = hash;
next();
}
});
});
//is the following function my best bet?
userSchema.path('username').validate(function (value, respond){
this.findOne({ username: value }, function (err, user){
if(user) respond(false);
});
}, 'This username has been already registered');
是我唯一的选择,省略了validation.usernameValidator方法,并使用userSchema.path验证用户名('用户名')。验证..?
答案 0 :(得分:2)
如果您在该字段上指定unique: true
,Mongoose应处理此问题。
例如
userSchema = mongoose.Schema({
username: {
type: String,
unique: true,
required: true
},
passwordHash: {
type: String,
required: true
},
email: {
type: String,
unique: true,
required: true
}
});
<强>此外:强>
Mongoose将声明一个唯一索引,前提是您在架构中指定了这个索引(如上例所示)。这可以防止必须查询到mongodb以查看另一个文档是否具有相同值的字段。你可以阅读它here。
如果您想了解有关其行为的更多信息,可以阅读有关mongodb here的唯一索引的详情。
注意:如果提供了非唯一值,则不会抛出验证错误。有关详细信息,请参阅mongoose文档。