MongoDB中bulkWrite与普通update的数组更新行为差异问题求助
问题:MongoDB bulkWrite 更新数组指定索引出现异常行为
我有一个包含order数组(存储ID)的文档。使用普通update操作设置数组特定索引元素时一切正常:
db.getCollection('myCollection').update( { _id: 'someId', }, { $set: { 'order.1': 'foo2', }, }, );
这个操作会更新数组的第二个元素;如果数组为空,第0个元素会被设为null。
但尝试用bulkWrite实现相同操作时出现异常:
db.getCollection('myCollection').bulkWrite([ { updateOne: { filter: { _id: 'eager' }, update: [ { $set: { 'order.1': 'foo3', }, }, ], }, }, ]);
如果数据库中的数组为空,此操作无任何效果;若数组已有元素,所有数组元素都会被替换为形如{'1': 'foo3'}的对象。
请问这是为什么?该如何让bulkWrite正常工作?
原因分析
你在bulkWrite的update字段里用了数组格式的更新语句,这会触发MongoDB的聚合管道式更新,而非普通的更新操作符模式。
两种模式下点语法的行为完全不同:
- 普通
update的操作符模式中,'order.1'会被正确识别为“数组的第1个索引位置”,空数组时还会自动扩展并填充null; - 聚合管道模式中,
'order.1'会被解析为“给数组内每个元素添加/修改名为1的字段”,空数组时则因为没有可操作的元素,导致无效果。
解决方法
把bulkWrite里的update字段从数组改成单个对象,切换回普通更新操作符模式即可:
db.getCollection('myCollection').bulkWrite([ { updateOne: { filter: { _id: 'eager' }, update: { $set: { 'order.1': 'foo3', }, }, }, }, ]);
修改后,bulkWrite的行为就会和普通update完全一致:
- 数组为空时,自动扩展数组并填充
null到第0位,同时设置第1位为'foo3'; - 数组已有元素时,仅更新第1个索引位置的元素。
内容的提问来源于stack exchange,提问作者Fuzzyma
相关产品推荐
相关产品推荐

