Mongoose调用update/findOneAndUpdate时无法验证数据类型如何解决?
问题根因
你已经全局开启了runValidators,所以required必填校验在更新操作中可以正常触发。类型校验不生效的核心原因是Mongoose对更新类操作默认开启了自动类型转换:比如你给String类型的字段传入数字123时,Mongoose会自动将其转换为字符串"123",符合Schema定义所以不会抛出错误。
解决方法
方案1:全局配置(推荐,适用于Mongoose 6及以上版本)
在Mongoose初始化配置的位置新增以下配置,全局禁用更新操作的自动类型转换,类型不匹配时直接抛出错误:
// 原有配置 mongoose.set('runValidators', true); // 新增配置 mongoose.set('strictQuery', true); mongoose.set('castOnUpdate', false);
方案2:单个查询单独配置
如果你不需要全局生效,也可以在对应的更新操作的查询参数中单独添加配置,修改你的更新接口代码如下:
const update = async (req, res) => { try { let post = await Post.findOneAndUpdate( req.params, req.body, { new: true, runValidators: true, // 显式开启当前查询的校验规则 cast: false // 禁用当前查询的自动类型转换 } ); res.json(post) } catch (e) { // 参数校验错误属于客户端请求错误,建议返回400状态码而非500 res.status(400).json(e) } }
方案3:自定义字段校验(全版本兼容)
如果使用的是Mongoose 5及更低版本,或者需要更灵活的校验规则,可以直接在Schema中给对应字段添加自定义类型校验器,插入和更新操作都会生效:
const Post = mongoose.model('Post', { nome: { type: String, required: true, trim: true, validate: { validator: function(v) { return typeof v === 'string'; }, message: props => `${props.value} 不是合法的字符串类型` } }, email: { type: String, required: true, trim: true, validate: { validator: function(v) { return typeof v === 'string'; }, message: props => `${props.value} 不是合法的字符串类型` } }, morada: { type: String, required: true, trim: true, validate: { validator: function(v) { return typeof v === 'string'; }, message: props => `${props.value} 不是合法的字符串类型` } } }) module.exports = Post
内容的提问来源于stack exchange,提问作者mlila_p
相关产品推荐
相关产品推荐

