在mongodb中更新子子数组中的元素

14

我在Mongo中有这份数据:

{
    "_id" : ObjectId("505fd43fdbed3dd93f0ae088"),
    "categoryName" : "Cat 1",
    "services" : [
        {
            "serviceName" : "Svc 1",
            "input" : [
                { "quantity" : 10, "note" : "quantity = 10" }, 
                { "quantity" : 20, "note" : "quantity = 20" }
            ]
        },
        {
            "serviceName" : "Svc 2",
            "input" : [
                { "quantity" : 30, "note" : "quantity = 30" }, 
                { "quantity" : 40, "note" : "quantity = 40" }
            ]
        }
    ]
}

现在我想更新“Svc 1”的数量:

{ "quantity" : 10, "note" : "quantity = 10" }

喜欢:

{"quantity": 100, "note": "changed to 100"}

我该如何在Mongo中操作?

据我所知,操作符只能支持第一个数组,有人建议使用子子数组元素的索引,但问题是如何在运行时知道那个索引?(我正在使用MongoDB的本机C#驱动程序)

提前感谢您的帮助!

Johnny

2个回答

15

由于您有一个嵌套数组,除非您知道要更新的数组位置,否则没有简单的方法引用嵌套的子数组。

所以,例如,您可以使用C#等效代码更新'Svc 1'的第一个输入:

db.services.update(

    // Criteria
    {
        '_id' : ObjectId("505fd43fdbed3dd93f0ae088"),
        'services.serviceName' : 'Svc 1'
    },

    // Updates
    {
        $set : {
            'services.$.input.0.quantity' : 100,
            'services.$.input.0.note' : 'Quantity updated to 100'
        }
    }
)

如果你不知道嵌套的input数组的位置,那么你需要获取匹配的services,在应用程序代码中迭代input数组,然后使用$set更新数组。

另外,你也可以修改嵌套的数组为一个嵌入式文档,例如:

{
    "categoryName" : "Cat 1",
    "services" : [
        {
            "serviceName" : "Svc 1",
            "input1" : { "quantity" : 10, "note" : "quantity = 10" }, 
            "input2" : { "quantity" : 20, "note" : "quantity = 20" }
        },
    ]
}

然后您可以按名称进行更新,例如input1

db.services.update(

    // Criteria
    {
        '_id' : ObjectId("5063e80a275c457549de2362"),
        'services.serviceName' : 'Svc 1'
    },

    // Updates
    {
        $set : {
            'services.$.input1.quantity' : 100,
            'services.$.input1.note' : 'Quantity updated to 100'
        }
    }
)

在MongoDB问题跟踪器中,有一个相关的请求[SERVER-267](部分通配符支持)。 - Stennie
感谢您的帮助,Stennie!我目前将输入和输出数组分组到另一个集合中作为解决方法。 - Johnny
请注意,如果嵌入的文档处于热状态,则可能会导致数据丢失。 - Oliver Dixon

8

由于您不知道要更新的值的位置,因此首先插入具有更新信息的新值,然后删除要更新的值。

db.services.update(
   {
    '_id' : ObjectId("505fd43fdbed3dd93f0ae088"),
    'services.serviceName' : 'Svc 1'
   },
   {
    { $addToSet: { 'services.$.input' : "new sub-Doc" }
   }
)

成功插入后再移除

db.services.update(
   {
    '_id' : ObjectId("505fd43fdbed3dd93f0ae088"),
    'services.serviceName' : 'Svc 1'
   },
   {
    { $pull: { 'services.$.input' : { "quantity" : 10, "note" : "quantity = 10" } }
   }
)

如果您不知道索引并且文档应该具有相同键的子文档(如“input”)以进行发布,则此方法非常有用。请参见在mongodb中更新子数组中的子元素


5
很有帮助,现在我会切换回MySql。谢谢。 - JSideris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接