0

I am trying to update nested subdocument in mongodb,

  {
id: 100, 
     status: [ { 

                 campaigns: [ 
                    { timestamp: "2014-07-30", 
                      task: [
                                { 
                                  id: "1",
                                  created: "2014-07-30"
                                } 

                        ]
                    }, 
                    { timestamp: "2014-07-31", 
                      task: [
                                { 
                                  id: "2",
                                  created: "2014-07-31" // need to update this field
                                } 

                        ]
                    }, 
                ]
            }, 
        ]

    }

Update Query

db.collectionname.update({"id": 100,"status.campaigns.task.id":"2"},{$set:{"status.0.campaigns.$.task.created:"2014-08-01"}});

the above query updates only first record (task.id = "1" created date) its not updating task.id="2" subdocument!!!!

Ayyanar G
  • 1,545
  • 1
  • 11
  • 24

2 Answers2

1

Nested Arrays The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value

Check the mongoDB docs on positional operator

So have you have three nested arrays status,campaigns,task. The positional operator will not work.

My guess is that the innermost position(innermost array) is stored in $. That's why you are getting $ as 0.

Follow the JIRA trackable for this issue if you are interested and vote for it.

ma08
  • 3,654
  • 3
  • 23
  • 36
  • For your current schema you can't do it in a single update query. A rethink of your schema might help. This is a known issu and a [JIRA Trackable](https://jira.mongodb.org/browse/SERVER-831) – ma08 Jul 31 '14 at 12:33
  • I need to do this in yiimongoDBsuite in php – Ayyanar G Jul 31 '14 at 12:36
  • It doesn't matter. MongoDB doesn't support positional operator for nested array. You should consider changing your schema. – ma08 Jul 31 '14 at 12:38
  • Can you suggest any schema design for above example ? – Ayyanar G Jul 31 '14 at 12:59
  • It isn't so simple. You need to consider a whole lot of factors like queries, read frequency, write frequency and stuff like that to design a good schema. [This site](http://dba.stackexchange.com) is more appropriate for stuff like that – ma08 Jul 31 '14 at 13:03
0

You can update the subdocument, but you need to know its position within the various nested arrays that you have in your document structure. This could be the case if say, you followed a specific numbering scheme for the id field of the subdocuments you insert into your nested arrays.

If that is a viable strategy for you, your update() would not require the second key/value pair in the first argument, because you are simply looking for the document containing the subdocument that you want to update and the _id field is unique. For the second argument, you would then use the indexes you would have for the position of the subdocument within the nested arrays.

For the example document you post, where you are updating the created field in the first element of the task array in the second element of the campaign array in the first element of the status array, then you do something as follows:

db.collection.update({ "_id": 100}, { $set: { "status.0.campaigns.1.task.0.created" : "2014-08-01" }});

If, however, you do not know the position of the subdocument you want to update, then you will not be able to update it. This is due to the fact that, as explained in the documentation, "the positional operator cannot be used for queries which traverse more than one array".

Juan Carlos Farah
  • 3,829
  • 30
  • 42