猫鼬:异步验证

时间:2017-12-09 16:42:27

标签: javascript node.js mongodb express mongoose

我正在使用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

感谢您的考虑,

1 个答案:

答案 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,所以猫鼬会抛出错误消息