Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update an element in sub of sub array in mongodb

I have this data in 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" }
            ]
        }
    ]
}

Now I want to update a quantity for "Svc 1":

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

Like:

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

How can I do with Mongo?`

As I know, operational operator only supports for the first array, someone advised to use index of an element of the sub sub array, but the problem is that how can know that index at run time? (I'm using native C# driver of MongoDB)

Thanks in advance for your helps!

Johnny

like image 227
Johnny Avatar asked Sep 27 '12 00:09

Johnny


People also ask

How do I change the nested array element in MongoDB?

Update Nested Arrays in Conjunction with $[]The $[<identifier>] filtered positional operator, in conjunction with the $[] all positional operator, can be used to update nested arrays. The following updates the values that are greater than or equal to 8 in the nested grades. questions array if the associated grades.

How do you update an array object in MongoDB?

To project, or return, an array element from a read operation, see the $ projection operator instead. To update all elements in an array, see the all positional operator $[] instead. To update all elements that match an array filter condition or conditions, see the filtered positional operator instead $[<identifier>] .

How do you update all elements in an array in MongoDB?

To update multiple elements, use []. The[] is an all positional operator indicating that the update operator should modify all elements in the specified array field.


2 Answers

Since you have an array within an array, there isn't any easy way to reference the nested subarray unless you know the position in the array you want to update.

So, for example, you could update the first input for 'Svc 1' with the C# equivalent of:

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'
        }
    }
)

If you don't know the position for the nested input array, you will have to fetch the matching services, iterate the input array in your application code, then $set the updated array.

Alternatively, you could modify your nested array to use an embedded document instead, eg:

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

Which you could then update by name, eg 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'
        }
    }
)
like image 81
Stennie Avatar answered Sep 19 '22 19:09

Stennie


Since you don't know the position of the value wanted to update, first insert a new value with updated information and then remove the value wanted to update.

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

And then remove when insert is success

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

This is useful when index is not known and document should have sub-documents having same key like "input" in post Update an element in sub of sub array in mongodb

like image 43
achuth Avatar answered Sep 19 '22 19:09

achuth