在NestJS中无法更新Mongoose从MongoDB查询到的文档属性
问题原因及解决方案
1 首要问题:异步循环写法错误
你使用了Array.prototype.forEach搭配异步回调函数,而forEach本身不支持等待异步操作执行完成,你写的await instance.save()并不会阻塞循环,代码执行到后续日志打印时,save操作实际还未完成提交,自然看不到更新后的结果。
修复方案:替换为支持异步等待的循环写法
比如使用for...of:
// note: getInstances just returns model.find() let instances: InstanceDocument[] = await this.instanceService.getInstances(); for (const instance of instances) { console.log(instance); let deviceCount = await this.instanceService.getDeviceCount(instance._id); let elementCount = await this.instanceService.getElementCount(instance._id) instance.deviceCount = deviceCount; instance.elementCount = elementCount; await instance.save(); console.log(deviceCount, elementCount, instance); }
如果需要更高的并发性能,也可以用Promise.all批量处理:
let instances: InstanceDocument[] = await this.instanceService.getInstances(); await Promise.all(instances.map(async instance => { let deviceCount = await this.instanceService.getDeviceCount(instance._id); let elementCount = await this.instanceService.getElementCount(instance._id) instance.deviceCount = deviceCount; instance.elementCount = elementCount; return instance.save(); }))
2 其他可能的原因
如果替换循环写法后仍然不生效,可以依次排查以下问题:
- Schema未定义对应字段:Mongoose只会持久化Schema中显式声明的字段,检查你的Instance Schema中是否定义了
deviceCount和elementCount两个字段,且字段类型和你赋值的类型匹配。 - Mongoose未检测到字段变更:部分场景下(比如修改嵌套子字段、混合类型字段)Mongoose无法自动识别字段变更,需要手动标记修改后再保存:
instance.deviceCount = deviceCount; instance.elementCount = elementCount; // 手动标记字段已修改 instance.markModified('deviceCount'); instance.markModified('elementCount'); await instance.save(); - 查询时使用了lean选项:如果
getInstances方法内部调用find()时加了lean()配置,返回的是普通JS对象而非Mongoose文档实例,不具备变更跟踪和save方法,移除lean()配置即可。
内容的提问来源于stack exchange,提问作者fonzane
相关产品推荐
相关产品推荐

