Mongoose更新totalOrders时出现NaN类型转换失败错误求助
问题描述
执行以下代码时触发类型错误:
const fullOrdersForService = service.totalOrders const updatedFullOrdersForService = fullOrdersForService + 1 const updateService = await Service.findOneAndUpdate({_id:serviceId}, { totalOrders: updatedFullOrdersForService },{new:true})
已确认service.totalOrders为Number类型且非NaN,Schema定义如下:
totalOrders:{ type:Number, required:true, default:0 }
错误信息:
messageFormat: undefined, stringValue: '"NaN"', kind: 'Number', value: NaN, path: 'totalOrders', reason: AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: assert.ok(!isNaN(val))
原因分析
- 竞态条件导致的并发冲突:先读取文档再修改更新的模式存在漏洞,当多个请求同时操作同一文档时,部分请求可能读取到旧值,计算后更新时触发Mongoose的类型验证异常。
- 模型中间件干扰:若Mongoose模型配置了
pre-update或pre-save钩子,钩子内的代码可能意外修改totalOrders的值,使其变为NaN。 - 隐性类型转换异常:尽管已确认当前
service.totalOrders为Number,但若文档曾被手动修改、数据迁移时出现类型不兼容,可能导致更新值在传输或验证环节被转为NaN。
解决办法
- 使用原子更新(推荐):利用MongoDB的
$inc操作符直接在数据库层面完成递增,彻底避免竞态问题,同时保证操作原子性:const updateService = await Service.findOneAndUpdate( { _id: serviceId }, { $inc: { totalOrders: 1 } }, { new: true } ); - 排查模型中间件:检查模型的
pre钩子函数,确保没有代码在更新流程中非法修改totalOrders字段。 - 添加防御性校验:在计算更新值时增加类型和有效性校验,避免无效值传入更新操作:
const fullOrdersForService = service.totalOrders; const updatedFullOrdersForService = typeof fullOrdersForService === 'number' && !isNaN(fullOrdersForService) ? fullOrdersForService + 1 : 1; // 可根据业务逻辑调整默认值 const updateService = await Service.findOneAndUpdate( { _id: serviceId }, { totalOrders: updatedFullOrdersForService }, { new: true } );
内容的提问来源于stack exchange,提问作者Nisandu Athsara
相关产品推荐
相关产品推荐

