node.js Mongoose 唯一验证错误类型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13580589/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 16:43:14  来源:igfitidea点击:

Mongoose unique validation error type

node.jsmongodbmongoose

提问by Olivier

I'm using this schema with mongoose 3.0.3from npm:

我正在使用mongoose 3.0.3来自 npm 的这个架构:

var schema = new Schema({

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

});

If I try to save a email that is already in db, I expect to get a ValidationErrorlike if a requiredfield is omitted. However this is not the case, I get a MongoError: E11000 duplicate key error index.

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

Which is not a validation error (happens even if I remove the unique:true).

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

Any idea why?

知道为什么吗?

回答by Mushex Antaranian

I prefer putting it in path validation mechanisms, like

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

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');

Then it'll just get wrapped into ValidationErrorand will return as first argument when you call validateor save.

然后它会被包裹ValidationError并在您调用validateor时作为第一个参数返回save

回答by Alex

This is expected behavior

这是预期的行为

The unique: trueis equivalent to setting an index in mongodb like this:

unique: true等同于这样的mongodb设置索引:

db.myCollection.ensureIndex( { "email": 1 }, { unique: true } )

To do this type of validation using Mongoose (Mongoose calls this complex validation- ie- you are not just asserting the value is a number for example), you will need to wire in to the pre-save event:

要使用 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();
});

回答by Sritam

I had some issues with the approved answer. Namely:

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

  1. this.model('User')didn't work for me.
  2. the callback donewasn't working properly.
  1. this.model('User')对我不起作用。
  2. 回调done没有正常工作。

I resolved those issues by:

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

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

I use async/awaitwhich is a personal preference because it is much neater: https://javascript.info/async-await.

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

Let me know if I got something wrong.

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