Mongoose使用bulkWrite时min/max验证规则不生效如何解决
问题原因
Mongoose 默认的 bulkWrite 批量操作会直接透传请求给 MongoDB 原生驱动,默认跳过 Schema 定义的验证逻辑,所以你定义的 min、max 规则不会生效。
解决步骤
1. 开启 bulkWrite 的验证开关
调用 bulkWrite 时,在第二个配置参数中添加 runValidators: true,即可开启更新验证逻辑:
// 修改bulkWrite的配置参数 Document.bulkWrite(myOperations, { runValidators: true }, (err, docs) => { // 原有业务逻辑不变 });
2. 处理 $inc 增量操作的特殊场景
注意:Mongoose 内置的 min、max 验证器默认只会校验你传入的更新值本身,如果你使用 $inc 传入的是增量值,内置验证器不会校验增量计算后的最终字段值是否符合范围要求。
比如当前 verificationcount 已经是 2,你传入的增量是 1,增量 1 本身符合 0~2 的规则,验证器不会报错,但最终计算结果为 3,超出了 max:2 的限制。
针对这种场景有两种常用处理方案:
方案1:在过滤条件中添加范围限制
生成批量操作时,在 filter 中添加规则,只有当前字段值加上增量后仍符合范围的文档才会被更新:const myOperations = req.body.documents.map((doc) => ({ updateOne: { filter: { _id: doc._id, // 确保verificationcount增量后仍在0~2范围内 verificationcount: { $lte: 2 - doc.verificationcount, $gte: 0 - doc.verificationcount }, // 确保verificationfailedcount增量后仍在0~2范围内 verificationfailedcount: { $lte: 2 - doc.verificationfailedcount, $gte: 0 - doc.verificationfailedcount } }, update: { $inc: { verificationcount: doc.verificationcount, verificationfailedcount: doc.verificationfailedcount, }, $addToSet: { opinionby: req.profile._id }, }, }, }));执行后可以通过 bulkWrite 返回结果中的
matchedCount字段判断是否所有文档都匹配成功,如果和传入的文档数量不一致,说明存在超出范围的更新请求,可自行处理异常逻辑。方案2:自定义预验证中间件
给 Schema 添加pre('bulkWrite')中间件,在批量操作执行前自行校验所有更新操作的合法性,适合规则复杂的场景。
可选方案(小数据量场景)
如果批量操作的文档数量不多,也可以先查询出所有需要修改的文档,逐个修改字段后调用 save() 方法,会自动触发完整的文档验证逻辑,但性能较低,不适合百条以上的批量操作。
内容的提问来源于stack exchange,提问作者Singh

