updating nested array elements

690 views
Skip to first unread message

Lavi Bharath

unread,
May 11, 2016, 12:55:39 AM5/11/16
to mongodb-user
I have a nested array as below. I am trying to update a nested array as below. But not able to complete the operation successfully
{
    "_id" : ObjectId("57304a006f42802df624aaa6"),
    "test" : "Milan",
    "timestamp" : NumberLong(1462781256018),
    "analysis" : [ 
        {
            "userName" : "xxx",
            "Status" : "SUCCESS",
            "startTime" : "2016-05-09T18-35-23.601813",
            "EndTimes" : "2016-05-09T18-40-02.891451",
            "analysis_id" : "2016-05-09T18-35-23.601813",
            "per_data_status" : [ 
                {
                    "id" : "3676",
                    "dir" : "Project_3676",
                    "Status" : "SUCCESS",
                    "StatsSubmission" : "TODO",
                    "ArchiveSubmission" : "TODO"
                },               
                {
                    "id" : "9009",
                    "dir" : "Project_9009",
                    "Status" : "SUCCESS",
                    "StatsSubmission" : "TODO",
                    "ArchiveSubmission" : "TODO"
                }
            ]
        }
    ]
}

db.getCollection('datacomplete').update(
    {test: "Milan", 'analysis.analysis_id' : "2016-05-09T18-35-23.601813", "analysis.per_data_status.id" : "9009"},
    {$set: 
        { 
            "per_mux_status.$": 
                    {
                    "id" : "9009",
                    "dir" : "9009",
                    "Status" : "SUCCESS",
                    "StatsSubmission" : "DONE",
                    "ArchiveSubmission" : "DONE"
                    }            
            }
        }      
)   

Thanks. PLease check my above query hence I am able to update

Wan Bachtiar

unread,
May 12, 2016, 3:31:59 AM5/12/16
to mongodb-user

But not able to complete the operation successfully

Hi Lavi,

Could you clarify what do you mean by not being able to complete the operation successfully ? If you are getting error messages, could you post them please ?

If I run your update operation on the example data you’ve given, it ran without errors. Perhaps you are looking for a different document outcome, for example if you are wanting to set per_mux_status field within the same analysis array element as per_data_status field in query, like below:

{ "test": "Milan",
  
"analysis": [
    {
      "userName": "xxx",
      "Status": "SUCCESS",
      "startTime": "2016-05-09T18-35-23.601813",
      "EndTimes": "2016-05-09T18-40-02.891451",
      "analysis_id": "2016-05-09T18-35-23.601813",
      "per_data_status"
: [
        { ... },
        { ... }
      ],
      "per_mux_status": {
        
"id": "9009",
        "dir": "9009",
        "Status": "SUCCESS",
        "StatsSubmission": "DONE",
        "ArchiveSubmission": "DONE"

      }
    }
  ]
}

You could replace per_mux_status.$ in your update operation with analysis.$.per_mux_status.

If the above is not what you are looking for, could you provide the following information:

  • MongoDB server version
  • An example of document result after update that you are trying to get.

Regards,

Wan.

Lavi Bharath

unread,
May 12, 2016, 9:29:48 PM5/12/16
to mongodb-user
Hi WAn,
Thanks.
Sorry for the confusion. Its per_data_status.

The original nested array is below(full data structure in the original post.

 {
                    "id" : "9009",
                    "dir" : "Project_9009",
                    "Status" : "SUCCESS",
                    "StatsSubmission" : "TODO",
                    "ArchiveSubmission" : "TODO"
                }

In this I just want to change two status and hence it gets updated as below:

 {
                    "id" : "9009",
                    "dir" : "Project_9009",
                    "Status" : "SUCCESS",
                    "StatsSubmission" : "DONE",
                    "ArchiveSubmission" : "DONE"
                }

Thanks for your time.

Wan Bachtiar

unread,
May 13, 2016, 2:15:27 AM5/13/16
to mongodb-user

Hi Lavi,

Currently, as of version v3.2 you won’t able to update nested arrays using $set. There is an open ticket in MongoDB jira tracker SERVER-831 to support $set for nested arrays, please feel free to watch and/or upvote for updates.

One work-around is to use .forEach to iterate through the arrays and update the document, example:

db.datacomplete.find({
    "test":"Milan", "analysis.analysis_id" : "2016-05-09T18-35-23.601813", "analysis.per_data_status.id" : "9009"})
    .forEach(
        function(doc){
            doc.analysis.forEach(function(a){ 
                if(a.analysis_id=="2016-05-09T18-35-23.601813"){
                    a.per_data_status.forEach(function(data){
                        if(data.id=="9009"){
                            data.StatsSubmission = "SUCCESS"; 
                            data.ArchiveSubmission = "DONE";
                        }
                    })
                }
            })
            db.datacomplete.save(doc) 
        })

Alternatively, you can modify the document schema to remove nested arrays. For example, depending on your application use case, you could store per_data_status into another collection. Another example to try is to use sub-document rather than array for analysis:

{
  "_id": ObjectId("57304a006f42802df624aaa6"),
  "test": "Milan",
  "timestamp": NumberLong("1462781256018"
),
  "analysis": {    
      /* Use username as the key per analysis */
      "xxx" : {
          
"Status": "SUCCESS",
          "startTime": "2016-05-09T18-35-23.601813",
          "EndTimes": "2016-05-09T18-40-02.891451",
          "analysis_id": "2016-05-09T18-35-23.601813",
          "per_data_status"
: [
          {
            
"id": "9009",
            "dir": "Project_9009",
            "Status": "SUCCESS"
,
            "StatsSubmission": "SUCCESS",
            "ArchiveSubmission": "TODO"
          }
        ]    
     }
   }
}

Different schemas have different benefits depending on your application use case. You may find the following useful:

Also to point out you may want to store the date values as BSON Date via Date(). Especially if you would like to query using date values later on.

Regards,

Wan.

Lavi Bharath

unread,
May 13, 2016, 2:52:12 AM5/13/16
to mongodb-user
Thanks Wan.

Lavi Bharath

unread,
May 13, 2016, 2:53:24 AM5/13/16
to mongodb-user
I will use your first example. Hope that resolves my current issue. I am using latest 3.2 version. 
Kindly appreciate your help. Thanks again for your time

Lavi Bharath

unread,
May 16, 2016, 2:02:18 AM5/16/16
to mongodb-user
The mongoDB commandline which Wan mentioned below works.
db.datacomplete.find({ "test":"Milan", "analysis.analysis_id" : "2016-05-09T18-35-23.601813", "analysis.per_data_status.id" : "9009"}) .forEach( function(doc){ doc.analysis.forEach(function(a){ if(a.analysis_id=="2016-05-09T18-35-23.601813"){ a.per_data_status.forEach(function(data){ if(data.id=="9009"){ data.StatsSubmission = "SUCCESS"; data.ArchiveSubmission = "DONE"; } }) } }) db.datacomplete.save(doc) })


Can someone let me know how to execute mongoDB command inside ppython script? I am using pymongo. I always get indent error. Thanks.

Wan Bachtiar

unread,
May 19, 2016, 12:57:09 AM5/19/16
to mongodb-user

Can someone let me know how to execute mongoDB command inside ppython script? I am using pymongo.

Hi Lavi,

The example below is written using pymongo v3.2 and MongoDB v3.2:

query = {'test': 'Milan', 
         'analysis.analysis_id': '2016-05-09T18-35-23.601813', 
         'analysis.per_data_status.id': '9009'}
new_document = collection.find_one(query)
if new_document:
    for a in new_document.get('analysis'): 
        if a.get('analysis_id') == analysis_id:
            for d in a.get('per_data_status'):
                if d.get('id') == data_status_id:
                    d['StatsSubmission'] = "DONE"
                    d['ArchiveSubmission'] = "DONE"
    collection.save(new_document)

Depending on the concurrency nature of your application, you may be interested to see Atomicity and Transactions. As mentioned previously, I would recommend to consider your document schema to remove the nested arrays to simplify your database operations.

Also worth mentioning that there is a free online course at MongoDB University to learn more about MongoDB. The next session for working with MongoDB Python Driver - M101P: MongoDB for Developers starts on the 24th May.

Best regards,

Wan.

Reply all
Reply to author
Forward
0 new messages