Node脚本中MongoDB updateMany无需exec()?多Mongoose版本适配疑问
关于Mongoose 4.x中update与updateMany的exec()差异问题
这个问题其实和Mongoose 4.x不同版本里方法的设计演变有关,我来给你拆解清楚:
原因分析
在你使用的mongoose@4.6.1版本中:
update()是比较早期的API,它返回的是一个Query对象,这个对象本身不会自动执行数据库操作,必须通过调用.exec()方法(或者调用.then())来触发异步执行,所以你之前写的update(...).exec()是正确的写法。updateMany()是在Mongoose 4.4版本才引入的新API,它的设计已经适配了Promise语法,返回的是一个thenable对象(可以直接被await处理),不需要额外调用.exec()就能执行。这也是为什么你用updateMany的时候不用加.exec()也能正常运行的原因。
而你其他数据库用的mongoose@4.11.7,可能已经对update()做了优化,让它也支持直接await,但因为dbOne用的是4.6.1,所以还是得遵循旧版本的规则。
适配方法
为了让你的代码在不同版本的Mongoose下都能保持一致且稳定,推荐两种方式:
1. 统一添加.exec()(最推荐)
不管是update()还是updateMany(),都统一加上.exec()方法。因为updateMany()返回的thenable对象也支持调用.exec(),这样你的代码风格会更统一,也不会因为版本差异出问题。比如:
try { // update 保持原有写法 await data.dbOne.CollectionOne.update({}, { $unset: { "attributeOne": "" }}, {multi: true}).exec(); // updateMany 也加上exec() await data.dbOne.CollectionOne.updateMany({}, { $set: { "attributeTwo": "value" }}).exec(); } catch (e) { console.log(e); }
这种方式不需要区分版本,对所有Mongoose 4.x版本都兼容。
2. 针对版本做条件处理(可选)
如果你不想统一加.exec(),可以通过判断当前连接使用的Mongoose版本来决定是否调用:
const mongooseVersion = data.dbOne.mongoose.version; try { let updateResult; if (mongooseVersion.startsWith('4.6.')) { // 4.6.x版本下update需要exec() updateResult = await data.dbOne.CollectionOne.update({}, { $unset: { "attributeOne": "" }}, {multi: true}).exec(); } else { // 更高版本可以直接await updateResult = await data.dbOne.CollectionOne.update({}, { $unset: { "attributeOne": "" }}, {multi: true}); } // updateMany 所有4.x版本都可以直接await(或者统一加exec()) await data.dbOne.CollectionOne.updateMany({}, { $set: { "attributeTwo": "value" }}); } catch (e) { console.log(e); }
不过这种方式会增加代码复杂度,除非有特殊需求,否则更推荐第一种统一写法。
内容的提问来源于stack exchange,提问作者thehme
相关产品推荐
相关产品推荐

