node.js 检查猫鼬验证错误的最佳方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14407007/
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:59:11  来源:igfitidea点击:

Best way to check for mongoose validation error

node.jsmongoose

提问by zemirco

I've got two validationfunctions for my usermodel

我的用户模型有两个验证函数

User.schema.path('email').validate(function(value, respond) {
  User.findOne({email: value}, function(err, user) {
    if(err) throw err;
    if(user) return respond(false);
    respond(true);
  });
}, 'EMAIL_EXISTS');

and the same for username

和同样的 username

User.schema.path('username').validate(function(value, respond) {
  User.findOne({username: value}, function(err, user) {
    if(err) throw err;
    if(user) return respond(false);
    respond(true);
  });
}, 'USERNAME_TAKEN');

They return errors in the following format

它们以以下格式返回错误

{ message: 'Validation failed',
  name: 'ValidationError',
  errors: 
    { username: 
      { message: 'Validator "USERNAME_TAKEN" failed for path username',
        name: 'ValidatorError',
        path: 'username',
        type: 'USERNAME_TAKEN' } } }

The error for the emailpath is similar. Is there a smarter way to check for those errors than the following?

email路径的错误类似。有没有比以下更聪明的方法来检查这些错误?

if (err && err.errors && err.errors.username) { ... }

This is kind of ugly.

这有点丑。

回答by Sergi Ramón

Technically you must check first the error name because not all errors are handled the same way. Then, based on the error name you must check for particular properties, as the errors property that comes with a ValidationError.

从技术上讲,您必须首先检查错误名称,因为并非所有错误的处理方式都相同。然后,根据错误名称,您必须检查特定属性,如 ValidationError 附带的错误属性。

Also you put the field name in the error type and this is redundant, it's better to use the same error type because in the error checking procedure you will get the field name also.

此外,您将字段名称放在错误类型中,这是多余的,最好使用相同的错误类型,因为在错误检查过程中,您还将获得字段名称。

So your code can be something like:

所以你的代码可以是这样的:

User.schema.path('email').validate(function(value, respond) {
  User.findOne({email: value}, function(err, user) {
    if(err) throw err;
    if(user) return respond(false);
    respond(true);
  });
}, 'exists');

User.schema.path('username').validate(function(value, respond) {
  User.findOne({username: value}, function(err, user) {
    if(err) throw err;
    if(user) return respond(false);
    respond(true);
  });
}, 'exists');

And then, the error checking procedure:

然后,错误检查程序:

if (err) {
  switch (err.name) {
    case 'ValidationError':
      for (field in err.errors) {
        switch (err.errors[field].type) {
          case 'exists':
            ...
            break;
          case 'invalid':
            ...
            break;
          ...
        }
      }
      break;
    default:
      ...
  }
}

If you want to shorten this, you have various options. If you only have one type of validation you can do it like this:

如果你想缩短它,你有多种选择。如果您只有一种类型的验证,您可以这样做:

if (err) {
  if (err.name == 'ValidationError') {
    for (field in err.errors) {
      ...
    }
  } else {
    // A general error (db, crypto, etc…)
    ...
  }
}

The minimal expression of the error check procedure would be similar to what you've wrote in your post:

错误检查程序的最小表达类似于您在帖子中所写的内容:

if (err) {
  for (field in err.errors) {
    ...
  }
}

This will work because if errors is not defined it will just ignore the for. But you're ignoring all other error types here.

这将起作用,因为如果未定义错误,它将忽略 for。但是您在这里忽略了所有其他错误类型。

I also think that these error layouts are a bit messing, but don't expect for this to change in a near future.

我也认为这些错误布局有点混乱,但不要指望在不久的将来会改变。

回答by Sudhanshu Gaur

Just write the following code and enjoy.

只需编写以下代码并享受。

if (err) {
    console.log('Error Inserting New Data');
    if (err.name == 'ValidationError') {
        for (field in err.errors) {
            console.log(err.errors[field].message); 
        }
    }
}

回答by steampowered

I use AngularJS, so ngRepeatdisplays my validation errors on the web form. All I need to do is return an array of error messages.

我使用 AngularJS,因此ngRepeat在 Web 表单上显示我的验证错误。我需要做的就是返回一组错误消息。

Sometimes Mongoose will throw an error which is NOT a validation error, and in this case the err.errors object will not be present. I log the execution error. I still use the same spot on the web form to display the execution error to the user.

有时 Mongoose 会抛出一个不是验证错误的错误,在这种情况下 err.errors 对象将不存在。我记录了执行错误。我仍然使用 Web 表单上的相同位置向用户显示执行错误。

var makeMongooseErrorMsgArray = function(err){
    var msgArray = [];
    if (err.errors) { // validation errors
        $.each(err.errors, function (key, val) {
            msgArray.push(val.message);
        });
    } else if (err.message){ // should be execution error without err.errors
        errLogr.log(err); // log execution errors
        msgArray.push(err.message);
    } else {
        msgArray.push('Unknown error');
    }
    return msgArray;
}

回答by Kunok

By reading all these answers, I consider it's the best to create utility function and reuse it as such:

通过阅读所有这些答案,我认为最好创建效用函数并重用它:

This is the function that handles ValidationErrorby sending desired response to the client with validation messages, and optionally uses console.logto show messages in console.

这是ValidationError通过向客户端发送带有验证消息的所需响应来处理的函数,并可选择用于console.log在控制台中显示消息。

function handleValidationError(err, res, consoleLog = false){
  const messages = []
  for (let field in err.errors) {
    messages.push(err.errors[field].message)
    consoleLog && console.log(err.errors[field].message)
  }
  res.status(422).json({ messages })
}

Then in controller where we want to handle error, we check if err.nameis ValidationError, and if so, we use utility function from above.

然后在我们想要处理错误的控制器中,我们检查是否err.nameValidationError,如果是,我们使用上面的效用函数。

user.save((err) => {
  if (err) {
    if (err.name === 'ValidationError') return handleValidationError(err, res) // here
    return res.status(500).json({ message: 'Error while creating new user' })
  }
  return res.status(201).json({ message: 'User created' })
})

Then client would get validation erros in response as such:

然后客户端会得到验证错误作为响应:

curl\
-H 'Content-Type: application/json'\
-d '{"email": "foo", "password": "barbaz"}'\
http://localhost:3000/user/new

Output:

输出:

{"messages":["Email validation failure"]}

回答by Aamir Afridi

I found this helpful which displays all errors in an array.

我发现这很有帮助,它显示了一个数组中的所有错误。

For example I submitted a form with short password and invalid email.

例如,我提交了一个带有短密码和无效电子邮件的表单。

if (err && err.name === 'ValidationError') {
   err.toString().replace('ValidationError: ', '').split(',')
}

Which results in this

这导致了这个

[ 'Please provide a valid email address',
'The password should be at least 6 characters long' ]

If you have a comma ,in your error messages than try without .split(',')

如果您,的错误消息中有逗号,请不要尝试.split(',')

No need for forloops. Make sure you have validation error messages in your schema. For the above example I have

不需要for循环。确保您的架构中有验证错误消息。对于上面的例子,我有

const validateEmail = email => {
  const re = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
  return re.test(email);
};

const Schema = mongoose.Schema;
const userSchema = new Schema({
   ...
   email: {
      type: String,
      trim: true,
      required: 'Email address is required',
      validate: [validateEmail, 'Please provide a valid email address'],
   },
   password: { type: String, set: encryptPassword, maxlength: [6, 'The password should be at least {MAXLENGTH} characters long'] },
   ...
});

回答by jviotti

Why don't you use the validationmethod as described in the API?

为什么不使用API 中描述validation方法?

objectToSave.validate(function(err) {          
  if (err) {
    // handle error
  }     
  else {
    // validation passed
  }
});

回答by Ankur Loriya

Here my unique way to handle mongoose validation error

这是我处理猫鼬验证错误的独特方法

The code is still in progress once it ready I will update it or you can contribute to extends my code.

一旦准备就绪,代码仍在进行中,我将对其进行更新,或者您可以为扩展我的代码做出贡献。

let message = "";
let title = "Validation Error";
let code = 400;
let requiredFields = [];
for (let field in err.errors) {
    let subMsg = ""
    if (err.errors[field].kind === "required") {
        requiredFields.push(field)
    }
}
if (requiredFields.length > 0) {
    message = "Following fields are required: " + requiredFields.join(", ");
} else {
    message = "Unknown";
}
res.status(code).json({
    status: code,
    message: message,
    title: title
});

回答by Danial Shabbir

Approach #1

方法#1

My Best Guess for this approach is to use generalized validator with promise based returns, hope it may help down the road

我对这种方法的最佳猜测是使用基于承诺的回报的广义验证器,希望它可以帮助未来

function validateDoc(model,fieldName) {
  return new Promise((resolve, reject) => {
    model.validate(err => {
      if (err) {
        return reject(err.errors[fieldName]);
      } else {
        return resolve(model);
      }
    });
  })
}

// Access error message in catch() or get the validated doc in then()

validateDoc(model,fieldName)
           .then((model) => console.log(model))
           .catch((message) => console.warn(message))

Approach #2

方法#2

const userSchema = new Schema({
  name: {
    type:String,
    required:[true,'Name is required.'],
    validate:{
      validator:(name) => { name.length > 2 }
      message:'Name must be longer than two characters'
    }
  }
})
const User = mongoose.model('user',userSchema)

Use the validate:Objectinside schema with validator:functionand message:String

validate:Object内部架构与validator:functionmessage:String 一起使用

Later when u will try to save the record it will thow the validation error object in the catch function

稍后当您尝试保存记录时,它会在 catch 函数中显示验证错误对象

For Example

例如

const newUser = new User({ name: undefined });

newUser.save().catch( ( { errors } ) => { 

let errorBag = [];

Object.keys(errors).forEach((fieldName) => {

errorMessages.push({ [fieldName]:errors[fieldName].message })

});

 // All the errors with the **fieldName** and  **errorMessages** 

console.log(errorBag);  

   })