28

我正在使用mongoose 3.0.3来自 npm 的这个模式:

var schema = new Schema({

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

});

如果我尝试保存已经在数据库中的电子邮件,我希望在省略字段的情况下得到一个ValidationErrorrequired。然而事实并非如此,我得到一个MongoError: E11000 duplicate key error index.

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

知道为什么吗?

4

5 回答 5

32

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

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

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

于 2014-02-27T22:30:06.010 回答
17

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

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

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

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

于 2019-02-16T08:04:40.893 回答
12

这是预期的行为

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

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

要使用 Mongoose 进行这种类型的验证(Mongoose 称之为复杂的验证——例如,你不只是断言该值是一个数字),你需要连接到 pre-save 事件:

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();
});
于 2012-11-27T10:14:36.737 回答
1

简单响应json

try {
  let end_study_year = new EndStudyYear(req.body);
  await end_study_year.save();
   res.json({
    status: true,
    message: 'បានរក្សាទុក!'
   })
  }catch (e) {
   res.json({
   status: false,
   message: e.message.toString().includes('duplicate') ? 'ទិន្នន័យមានរួចហើយ' : e.message.split(':')[0] // check if duplicate message exist
  })
 }
于 2020-09-19T09:56:27.043 回答
1

抱歉回答了一个老问题。经过测试,我感觉很好,找到了这些答案,所以我将给出我的经验。两个最佳答案都很好而且正确,请记住:

  • 如果您的文档是新的,您可以验证计数是否高于 0,这是常见的情况;
  • 如果您的文档不是新文档并且已修改该unique字段,则您也需要使用 0 进行验证;
  • 如果您的文档不是新的并且没有被修改,请继续;

这是我在代码中所做的:

UserSchema.path('email').validate(async function validateDuplicatedEmail(value) {
    if (!this.isNew && !this.isModified('email')) return true;

    try {
        const User = mongoose.model("User");

        const count = await User.countDocuments({ email: value });
        if (count > 0) return false;

        return true;
    }
    catch (error) {
        return false;
    }
}, "Email already exists");


于 2022-01-15T13:51:31.847 回答