Joe
Joe

Reputation: 871

Mongo DB modify elements in nested arrays

I am wondering how can I change the element in such array in Mongo DB. Say the collections is as follow:

{
"_id" : ObjectId("xxxxxxxxxxxxxxxx"),

"user_info" : {
    "user_name" : "joe",        
},

"portfolio" : [ 
    {
        "market_symbol" : "NASDAQ:GOOGL",
        "details" : [ 
            {
                "amount" : 100,
                "purchased_price" : 810.25,
                "date_of_purchase" : "20170210 212426"
            }, 
            {
                "amount" : 100,
                "purchased_price" : 810.25,
                "date_of_purchase" : "20170210 212426"
            }, 
            {
                "amount" : 200,
                "purchased_price" : 900.0,
                "date_of_purchase" : "20170210 212426"
            }
        ]
    }, 
    {
        "market_symbol" : "NYSE:BABA",
        "details" : [ 
            {
                "amount" : 200,
                "purchased_price" : 80.0,
                "date_of_purchase" : "20170210 212426"
            }, 
            {
                "amount" : 333,
                "purchased_price" : 86.11,
                "date_of_purchase" : "20170210 212426"
            }
        ]
    }
]

I am trying to modify the value of amount in "portfolio:market_symbol":"NASDAQ:GOOGL", where the purchased_price is 900 and I want to set the 200 to 300.

so the segment should look like this after the modification:

"portfolio" : [ 
{
    "market_symbol" : "NASDAQ:GOOGL",
    "details" : [ 
        {
            "amount" : 100,
            "purchased_price" : 810.25,
            "date_of_purchase" : "20170210 212426"
        }, 
        {
            "amount" : 100,
            "purchased_price" : 810.25,
            "date_of_purchase" : "20170210 212426"
        }, 
        {
            "amount" : 300,
            "purchased_price" : 900.0,
            "date_of_purchase" : "20170210 212426"
        }
    ]
}, 

I tried to use $elemMatch in mongo shell

db.Users.update({"user_info.user_name":"joe","portfolio":{$elemMatch:{"market_symbol":{$eq:"NASDAQ:GOOGL"},"details.purchased_price":{$eq:900}}}},{$set:{"portfolio.$.details.0.amount":300}})

It seems that the query always return the entire section of "portfolio:market_symbol":"NASDAQ:GOOGL", because the 0 in {$set:{"portfolio.$.details.0.amount":300}} modifies the first array in details, whose purchased_price is 810.25, rather than what I expect the $elemMatch to give me (the 3rd element from the array, whose purchased_price is 900).

Is there a way that I can modify this nested nested array, rather than pulling the entire thing off, modify the data in my program, then write the entire thing back?

Please help, thanks.

Upvotes: 1

Views: 250

Answers (1)

McGrady
McGrady

Reputation: 11477

As far as I know,the positional operator only supports one level deep and only the first matching element.So that means updating all documents in array is not possible now.

There is a MongoDB JIRA ticket: https://jira.mongodb.org/browse/SERVER-831

But you can update specific document manually.

db.test.find( 
{ "user_info.user_name":"joe", "portfolio.details.purchased_price" : 900.0 }).forEach(function(doc) { 
  doc.portfolio.forEach(function(item) { 
      item.details.forEach(function (amt){
            if (amt.purchased_price == 900.0)
                amt.amount=300
          });
      });
  db.test.update( { "user_info.user_name":"joe", "portfolio.details.purchased_price" : 900.0 }, { "$set": { "portfolio": doc.portfolio } });
});

It works for me.Hope this helps.

Upvotes: 1

Related Questions