使用Mongoose的自定义错误消息

时间:2016-08-14 18:59:38

标签: node.js mongodb error-handling mongoose

因此根据mongoose docs,您应该能够在架构中设置自定义错误消息,如下所示:

 var breakfastSchema = new Schema({
  eggs: {
    type: Number,
    min: [6, 'Too few eggs'],
    max: 12
  },
  bacon: {
    type: Number,
    required: [true, 'Why no bacon?']
  }
});

所以我想做类似的事情:

var emailVerificationTokenSchema = mongoose.Schema({
   email: {type: String, required: true, unique: [true, "email must be unique"]},
   token: {type: String, required: true},
   createdAt: {type: Date, required: true, default: Date.now, expires: '4h'}
});

这个想法是,当你试图保存其中一个令牌并且已经存在冲突时,它会输出一条错误消息,上面写着"电子邮件必须是唯一的"。

然而,当我做这样的事情时(我使用相同的电子邮件保存令牌):

verificationToken.save( function (err) {
    if (err) {
      return console.log(err);
    }
    else {
      return console.log(err);
    }
});

我一直这样:

'E11000 duplicate key error: index ___.emailVerificationToken.$email_1 dup key: { : "_____@wdad.com

有什么想法?自定义消息不支持唯一参数吗?这是一种可行的做事方式吗?

10 个答案:

答案 0 :(得分:15)

  

自定义消息不支持唯一参数吗?

Mongoose中的唯一性不是验证参数(如Tool);它告诉Mongoose在MongoDB中为该字段创建一个唯一索引。

唯一性约束完全在MongoDB服务器中处理。当您添加具有重复键的文档时,MongoDB服务器将返回您显示的错误(required)。

如果要创建自定义错误消息,则必须自己处理这些错误。 Mongoose documentation"错误处理中间件" )为您提供了有关如何创建自定义错误处理的示例:

E11000...

(虽然这并没有为您提供唯一性约束失败的特定字段)

答案 1 :(得分:2)

verificationToken.save( function (err) {
    if (err) {
      return res.status(400).send({
          message: (err.name === 'MongoError' && err.code === 11000) ? 'Email already exists !' : errorHandler.getErrorMessage(err)
      });
    }
    else {
      return console.log('No Error');
    }
  });

答案 2 :(得分:1)

Mongoose 5.x.x的更新版本

MySchema.post('save', function (error, doc, next) {
    if (err.name === 'BulkWriteError' && error.code === 11000) 
        next(new Error('This item already exists, please try again'));
    else next(error);
});

答案 3 :(得分:1)

只需应用中间件。

recordingSchema.post('save', function (error, _, next) {
    next( error.code === 11000 
      ?   new Error('This item field already exist')
      :   error)
});

答案 4 :(得分:1)

来自 Schema 的唯一值的错误消息确实对人类不友好。 这让我很不安,但是当我看到错误对象中剩余的键时,我能够设置它。

在返回错误消息时,

 document.save().then(() => {
        return res.status(201).json({
          statusText: "created",
          message: "document created successfully",
          data: brand,
        });
      })
      .catch((error) => {

        // Set custom error for unique keys
        let errMsg;
        if (error.code == 11000) {
          errMsg = Object.keys(error.keyValue)[0] + " already exists.";
        } else {
          errMsg = error.message;
        }
        res.status(400).json({ statusText: "Bad Request", message: errMsg });
      });

答案 5 :(得分:0)

感谢所有答案,我已经解决了我的问题。

我的模式就是这样。

var User = new Schema({
  username: {type: String, required: [true, "Username is required"], unique: true},
  email: {type: String, required: [true, "Email is required"], unique: true},
  password: {type: String, required: true, unique: false},
});

我建议像函数一样使用。

您可以这样使用

User.post("save", function (error, doc, next) {

  if (error.keyValue.email != null && error.name === "MongoError" && error.code === 11000) {

    console.log("Email must be unique");
  } else if (error.keyValue.username != null && error.name === "MongoError" && error.code === 11000) {
    console.log("Username must be unique");
  } else {
    console.log("not found any idea, search for another reasons");
  }
});

答案 6 :(得分:0)

您可以添加自定义异步验证器。例如:

 {
      validator: (value) => {
        return UserModel.findOne({ email: value })
          .then(user => Promise.resolve(user == null))
          .catch(error => Promise.reject(false));
      },
      message: "User with this email already exists"
 }

答案 7 :(得分:0)

我是这样处理的:

schema.post('save', function (error, doc, next) {
    let errorMessage

    // map with all unique items you defined in your schema 
    const errorsMap = {
        email: 'your message for existing email',
        otherUniqueItem: 'your message for existing item',
    }

    if (error.code === 11000) {
        errorMessage = Object
            .keys(error.keyValue)
            .map(key => errorMap[key])
            .join(', ')
    } else {
        errorMessage = error.message
    }

    if (errorMessage) next(new Error(errorMessage))
    else next()
})

答案 8 :(得分:0)

更新的 mongoose 版本 5.x.x 支持此特定要求。

https://mongoosejs.com/docs/middleware.html#error-handling-middleware

您可以为架构添加 post 方法并按照以下操作: // 保存用户后,如果用户重复,返回错误

userSchema.post('save', function(error: any, doc: any, next: any) {
  if (error.name === 'MongoError' && error.code === 11000) {
    next(new Error('user_exists'));
  } else {
    next();
  }
});

答案 9 :(得分:-1)

您可以在源代码中重写错误消息,在节点模块中也可以。这是执行此操作的路径: YOUR_PROJECT / node_modules / mongoose / lib / error / validation.js

那么您就没有任何其他软件包问题了。