Mongoose唯一验证错误类型

Oli*_*ier 19 mongoose mongodb node.js

mongoose 3.0.3从npm 使用这个架构:

var schema = new Schema({

    _id: Schema.ObjectId,
    email: {type: String, required: true, unique: true}

});
Run Code Online (Sandbox Code Playgroud)

如果我尝试保存已经在db中的电子邮件,我希望在省略字段时得到ValidationError类似的信息required.然而事实并非如此,我得到了一个MongoError: E11000 duplicate key error index.

这不是验证错误(即使我删除unique:true也会发生).

知道为什么吗?

Mus*_*ian 28

我更喜欢把它放在路径验证机制中,比如

UserSchema.path('email').validate(function(value, done) {
    this.model('User').count({ email: value }, function(err, count) {
        if (err) {
            return done(err);
        } 
        // If `count` is greater than zero, "invalidate"
        done(!count);
    });
}, 'Email already exists');
Run Code Online (Sandbox Code Playgroud)

然后,它会一下就裹成ValidationError,当你调用返回的第一个参数validatesave.

  • @ user3344977为什么这比预保存功能更好? (2认同)
  • 上面的代码给出 **DeprecationWarning**: *collection.count 已弃用,并将在未来版本中删除* (2认同)

Sri*_*tam 14

我对批准的答案有一些问题。即:

  1. this.model('User') 对我不起作用。
  2. 回调done没有正常工作。

我通过以下方式解决了这些问题:

  UserSchema.path('email').validate(async (value) => {
    const emailCount = await mongoose.models.User.countDocuments({email: value });
    return !emailCount;
  }, 'Email already exists');
Run Code Online (Sandbox Code Playgroud)

我使用async/await这是个人偏好,因为它更整洁:https : //javascript.info/async-await

如果我有什么问题,请告诉我。


Ale*_*lex 11

这是预期的行为

unique: true相当于在mongodb中设置索引,如下所示:

db.myCollection.ensureIndex( { "email": 1 }, { unique: true } )
Run Code Online (Sandbox Code Playgroud)

要使用Mongoose进行这种类型的验证(Mongoose称这种复杂的验证 - 即 - 您不仅仅是断言值是一个数字),您需要连接到预存储事件:

mySchema.pre("save",function(next, done) {
    var self = this;
    mongoose.models["User"].findOne({email : self.email},function(err, results) {
        if(err) {
            done(err);
        } else if(results) { //there was a result found, so the email address exists
            self.invalidate("email","email must be unique");
            done(new Error("email must be unique"));
        } else {
            done();
        }
    });
    next();
});
Run Code Online (Sandbox Code Playgroud)