Mongoose bulkWrite upsert仅能创建文档无法更新的问题排查
问题
尝试用Mongoose 5.4实现批量upsert操作,参考相关方案后编写代码如下:
const update = await Company.bulkWrite([ { 'updateOne': { 'filter': { 'url': result.url }, 'update': { testVal: 'testinggg' }, 'upsert': true, } }, ]);
执行后得到响应:
{ "ok": 1, "writeErrors": [], "writeConcernErrors": [], "insertedIds": [], "nInserted": 0, "nUpserted": 0, "nMatched": 1, "nModified": 1, "nRemoved": 0, "upserted": [] }
但实际文档并未更新。修改filter创建新文档时正常,但匹配到现有文档时无法完成更新,尝试使用$set也无效:
const update = await Company.bulkWrite([ { 'updateOne': { 'filter': { 'url': result.url }, 'update': { '$set': { testVal: 'testinggg' } }, 'upsert': true, } }, ]);
分析与解决方案
出现该问题通常有以下几种原因及对应解决办法:
版本兼容性bug
Mongoose 5.4属于较旧版本,存在批量操作相关的已知bug。建议升级到5.x系列的稳定子版本(如5.13.x),或直接更新至更高版本,新版本已修复此类批量更新异常问题。Schema定义限制
检查Company模型的Schema配置:- 确认
testVal字段已在Schema中定义,且未设置immutable: true这类禁止修改的属性; - 若
testVal是新增字段,Schema默认的strict: true会阻止未定义字段被写入,可在update操作中添加strict: false选项,或修改Schema添加该字段:const update = await Company.bulkWrite([ { 'updateOne': { 'filter': { 'url': result.url }, 'update': { '$set': { testVal: 'testinggg' } }, 'upsert': true, 'options': { strict: false } } }, ]);
- 确认
Filter匹配的隐形差异
尽管响应显示nMatched: 1,但result.url可能与文档中url存在隐形差异(如大小写、前后空格、编码不一致)。直接在MongoDB客户端执行db.companies.find({url: "你的result.url实际值"}),确认匹配到的文档是否为目标文档,且字段值无异常。未提交的事务或索引同步问题
若代码中存在未完成的事务,会导致更新未持久化;如果url是索引字段,可尝试在操作后执行await Company.syncIndexes()确保索引同步,避免匹配异常。
内容的提问来源于stack exchange,提问作者snn
相关产品推荐
相关产品推荐

