我正在使用Express + Mongo设计应用程序。 我想知道mongoose是否有任何同步验证功能?
认为这样的场景, 我正在使用我的自定义验证语句检查现有的电子邮件路径,如<; p>
UserSchema.path('email').validate(function (email, fn) {
const User = mongoose.model('User');
if (this.isNew || this.isModified('email')) {
User.find({ email: email }).exec(function (err, users) {
fn(!err && users.length === 0);
});
} else fn(true);
}, 'Email already exists');
关于mongoose的文档,
验证是异步递归的;当你打电话给Model#save时, 也执行子文档验证。如果发生错误,您的 模型#save callback接收它
电子邮件检查的验证当然必须是同步的。如果不是,它将导致严重的不合适。如果两个用户同时请求同一封电子邮件,那么mongoose将接受其中两个。
在模型的模型字段定义上设置unique
是否解决了问题?
我问这个是因为在我的应用程序中有一个匹配的系统。 如果条件满足,我匹配两个用户并创建匹配文档,如;
{
"_id" : ObjectId("5a2b30396aa5a754ccbfe63c"),
"checkin" : [
ObjectId("5a2b2ff96aa5a754ccbfe639"),
ObjectId("5a2b2fea6aa5a754ccbfe638")
],
"user" : [
ObjectId("5a29ece139205a12b5afd47e"),
ObjectId("5a29924bf3dc4b8dd881a307")
],
"createdAt" : ISODate("2017-12-09T00:37:13.221Z"),
"__v" : 0
}
构建具有相同用户的match
实体非常危险。
为了控制复制,首先我查询最近的集合以检查是否存在两个用户的匹配实体,如果没有则构建匹配实体并将其保存到集合中。
但昨天我发现了一个错误,当两个客户端同时请求时,该操作表现为异步并构建文档副本。
请告诉我如何处理这个问题。
我知道将匹配关系文档建模到用户的文档中,因为子文档解决了问题。因为那时我正在使用findAndUpdate
,我确信单个文档上的mongoDB更新是atomic
。
感谢您的考虑,
答案 0 :(得分:0)
“唯一”属性不用于验证。它只是有助于更快的查询。如果您为电子邮件设置了unique:true
,则在查询电子邮件地址时,猫鼬一旦找到正确的电子邮件,它将停止查询。因为它知道它是唯一的。
对于电子邮件的验证,我建议您使用一个非常流行的名为验证器的npm软件包:
https://www.npmjs.com/package/validator
这是在您的模式中实现它的方法:
const mongoose = require("mongoose");
const validator = require("validator");
const userSchema = new mongoose.Schema({
userName: {
type: String,
required: true
},
email: {
type: String,
required: true,
lowercase:true,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error("email is not valid");
}
}
},
});
validate是猫鼬自定义验证器。在此内部,我们使用验证程序包方法。对于电子邮件的价值,验证程序包会检查它是否不是有效的电子邮件,
!validator.isEmail(value)
这将返回false,所以猫鼬会抛出错误消息