为什么Mongoose的updateMany()方法需加.then()才会执行?
问题原因
Mongoose 中包括updateMany()在内的所有查询方法,返回值都不是原生Promise,而是内置的Query对象,这类对象默认是惰性执行的:
- 单独调用
Movie.updateMany(xxx)时,仅在本地构造了一个查询操作实例,不会向MongoDB服务端发送任何实际请求 - 只有对这个Query实例执行以下任意一种操作时,数据库操作才会真正触发:
- 链式调用
.then()/.catch()进入Promise处理链 - 在async函数中使用
await等待该实例 - 显式调用
.exec()方法提交操作
- 链式调用
为什么存在不加.then()也能运行的写法
你看到的无.then()写法通常属于两种情况:
- 代码使用了
await语法等待updateMany()执行,async/await作为语法糖,本质也是识别thenable对象触发执行 - 依赖了Mongoose旧版本(v6以前)的非稳定隐式执行逻辑:当未被处理的Query对象被垃圾回收时,会自动提交查询。这个行为从未被写入官方文档,属于副作用逻辑,Mongoose v6及之后版本已经完全移除了这个不稳定特性,不推荐任何场景下依赖该行为。
执行效果验证
你可以直接运行以下代码对比差异:
不会触发数据库修改的写法
// 仅构造查询对象,无触发逻辑,数据库数据不会变更 Movie.updateMany({year: {$in: [1992,2019]}}, {rating: 'M'})
可正常触发修改的三种写法
// 1. then链触发 Movie.updateMany({year: {$in: [1992,2019]}}, {rating: 'M'}).then(data => console.log(data)) // 2. await触发(需在async函数环境中使用) const updateRes = await Movie.updateMany({year: {$in: [1992,2019]}}, {rating: 'M'}) console.log(updateRes) // 3. 显式调用exec触发,不需要接收返回值也会执行 Movie.updateMany({year: {$in: [1992,2019]}}, {rating: 'M'}).exec()
注意:只要操作被触发,哪怕你不接收、不打印返回结果,修改也会正常同步到数据库,和你是否在代码中获取返回数据没有关系。你之前在Mongo Shell中看不到数据变化,本质是操作根本没有被发送到数据库。
内容的提问来源于stack exchange,提问作者Mats
相关产品推荐
相关产品推荐

