如何修改数组中特定子文档中的字段?

Posted

技术标签:

【中文标题】如何修改数组中特定子文档中的字段?【英文标题】:How to modify fields in specific sub-documents in an array? 【发布时间】:2021-02-05 22:01:20 【问题描述】:

我有一个集合,其中每个文档都有一个包含多个字段的子文档数组。我需要根据它们的字段更新特定的子文档,但是到目前为止我所做的每一次尝试都会更改所有排列的子文档中的字段

这里是一些示例数据:

 
    '_id' : ObjectId('0001'),
    'Region' : 'Northern',
    "Items" : [
        
            "ItemId" : NumberInt(25), 
            "Name" : "Widget", 
            "ProductType" : "15", 
            "ItemIdLegacy" : "ca-000037"
        , 
        
            "ItemId" : NumberInt(30), 
            "Name" : "Gizmo", 
            "ProductType" : "15", 
            "ItemIdLegacy" : "ca-000038"
        ,
        
            "ItemId" : NumberInt(35), 
            "Name" : "Thingy", 
            "ProductType" : "15", 
            "ItemIdLegacy" : "ca-000039"
        
    ] 

当我尝试对以下查询使用 update() 时,它会更新所有数组项的 ProductType,而不仅仅是我要更改的那个。

为了澄清,我想将带有 ItemIdLegacy: "ca-000038" 的数组项更改为 ProductType: 20。所有其他数组项应保持不变。我尝试过的查询:

db.Collection.update("Items.ItemIdLegacy" : "ca-000038",[$set:  "Items.ProductType" : "20" ],multi: false);

这是想要的输出:

 
    '_id' : ObjectId('0001'),
    'Region' : 'Northern',
    "Items" : [
        
            "ItemId" : NumberInt(25), 
            "Name" : "Widget", 
            "ProductType" : "15", 
            "ItemIdLegacy" : "ca-000037"
        , 
        
            "ItemId" : NumberInt(30), 
            "Name" : "Gizmo", 
            "ProductType" : "20", 
            "ItemIdLegacy" : "ca-000038"
        ,
        
            "ItemId" : NumberInt(35), 
            "Name" : "Thingy", 
            "ProductType" : "15", 
            "ItemIdLegacy" : "ca-000039"
        
    ] 

但这是运行该查询的实际输出:

 
    '_id' : ObjectId('0001'),
    'Region' : 'Northern',
    "Items" : [
        
            "ItemId" : NumberInt(25), 
            "Name" : "Widget", 
            "ProductType" : "20", 
            "ItemIdLegacy" : "ca-000037"
        , 
        
            "ItemId" : NumberInt(30), 
            "Name" : "Gizmo", 
            "ProductType" : "20", 
            "ItemIdLegacy" : "ca-000038"
        ,
        
            "ItemId" : NumberInt(35), 
            "Name" : "Thingy", 
            "ProductType" : "20", 
            "ItemIdLegacy" : "ca-000039"
        
    ] 

我觉得我错过了一些简单的东西......

编辑:我有一个查询可以让我更新数组中的单个匹配元素,但是我有数千个需要完成,因此一次性不一定有效(当然我可以将它们全部解析出来并向 shell 发送垃圾邮件,但我想要更优雅的东西)

单元素更新:

db.Collection.updateOne("Items.ItemIdLegacy" : "ca-000038", $set:  "Items.$.ProductType" : "20"   );

【问题讨论】:

【参考方案1】:

试试这个:-

db.collection.update(
  "Items.ItemIdLegacy": "ca-000038"
,

  $set: 
    "Items.$.ProductType": 20
  
,

  multi: true
)

这里是Working Example

【讨论】:

尝试运行时产生错误:[js] Error: the update operation document must contain atomic operators。此外,样本很小,但我有数千个适用项目分布在数百个文档的数组中,需要一种允许我编辑批量值的方法 您使用的是哪个版本的 mongo? v4.0.16 是我的版本 以上查询使用 4.2 的功能。我将尝试为 4.0 编写查询 谢谢,它适用于跨多个文档更新单个项目,但不允许在同一个数组中进行多个更新(例如 ItemIdLegacy: $in: [A, B, C] )。根据我对问题的阅读所收集到的信息,Mongo 可能无法做到这一点

以上是关于如何修改数组中特定子文档中的字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何匹配MongoDB中的子文档数组?

如何对数组字段中的子文档进行排序?

如何使用猫鼬更新子文档数组中的特定元素? [复制]

如何使用Mongoose和MongoDB 2.6插入子文档中数组中的特定位置

如何使用Mongoose和MongoDB 2.6插入子文档中数组中的特定位置

重命名数组中的子文档字段