MongoDB更新数组内对象属性时为何会插入新属性同时删除原有属性?
问题分析与解决方案
哦,我完全懂你遇到的坑了!你当前的更新操作其实是直接替换了整个cancelledTrains数组,而不是给数组内部的对象新增属性——这就是原有info属性消失的原因。
错误原因拆解
你执行的代码:
db.stations.updateOne({ name: 'stationXYZ' }, { $set: {cancelledTrains: {date: new Date("2022-02-14T15:49:00Z")} }})
这里的$set是把cancelledTrains字段的整个值替换成你传入的{date: ...}对象,直接覆盖了原来的数组[{ 'info': 'infoinfoinfo' }],自然就丢失了原有属性。
正确操作方式
要给数组内的对象新增/更新属性,需要用点符号结合数组定位符来精准操作数组内部的元素,而不是替换整个数组。根据你的需求,分三种常见场景:
1. 给数组中所有对象新增date属性
如果你想让数组里每一个火车对象都加上date属性,用数组通配符$[]:
db.stations.updateOne( { name: 'stationXYZ' }, { $set: { "cancelledTrains.$[].date": new Date("2022-02-14T15:49:00Z") } } )
$[]会遍历数组中的每一个元素,给它们都新增date属性,完全保留原有info字段。
2. 给数组中符合特定条件的对象新增date属性
如果你只想给某个匹配特定条件的火车对象加属性(比如匹配info值),用arrayFilters数组过滤器:
db.stations.updateOne( { name: 'stationXYZ' }, { $set: { "cancelledTrains.$[train].date": new Date("2022-02-14T15:49:00Z") } }, { arrayFilters: [{ "train.info": "infoinfoinfo" }] } )
这里arrayFilters定义了筛选规则,只有info等于infoinfoinfo的数组元素才会被更新,$[train]对应过滤器里的别名。
3. 给数组中指定位置的对象新增date属性
如果你确定要更新数组的第一个元素(或者固定索引的元素),直接用索引值:
db.stations.updateOne( { name: 'stationXYZ' }, { $set: { "cancelledTrains.0.date": new Date("2022-02-14T15:49:00Z") } } )
0是数组的第一个元素索引,这种写法精准定位到目标元素,新增属性的同时保留原有内容。
内容的提问来源于stack exchange,提问作者user6377312
相关产品推荐
相关产品推荐

