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!!!!

3
  • Why are you using status.0? Do you need to update only the first entry in status array? Commented Jul 31, 2014 at 12:06
  • problem in campaings positional param not status array Commented Jul 31, 2014 at 12:12
  • You can update the task if you want, but you need to know its position within the arrays. Do you know that beforehand? Commented Jul 31, 2014 at 13:41

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

5 Comments

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
I need to do this in yiimongoDBsuite in php
It doesn't matter. MongoDB doesn't support positional operator for nested array. You should consider changing your schema.
Can you suggest any schema design for above example ?
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 is more appropriate for stuff like that
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".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.