4

I am having difficulty updating nested json structure in mongo. I am using pymongo along with Mongoengine-Rest-framework.

Since this particular json has dynamic structure and is heavily nested, I chose to use pymongo over mongo-engine ORM.

The create, retrieve and delete operations faring fine. I would like some suggestions on the updation issue.

Lets consider a sample object which is already present in mongo:

st1 = {
        "name": "Some_name",
        "details": {
                    "address1": {
                        "house_no": "731",
                        "street": "Some_street",
                        "city": "some_city"
                            "state": "some_state"
                        }
                }
        }

If I try to update st1 by adding address2 to the details by sending the json st2 in the update command with _id being the condition for updation,

st2 = {
        "details": {
                    "address2": {
                        "house_no": "5102",
                        "street": "Some_street",
                        "city": "some_city"
                            "state": "some_state"
                        }
                }
        }

I get the following object st3 as result , in mongo,

st3 = {
        "name": "Some_name",
        "details": {
                    "address2": {
                        "house_no": " 5102",
                        "street": "Some_street",
                        "city": "some_city"
                            "state": "some_state"
                        }
                }
        }

instead of the expected st4 object.

st4 = {
        "name": "Some_name",
        "details": {
                    "address1": {
                        "house_no": "731",
                        "street": "Some_street",
                        "city": "some_city"
                            "state": "some_state"
                        },
                    "address2": {
                        "house_no": "5102",
                        "street": "Some_street",
                        "city": "some_city"
                            "state": "some_state"
                        }
                }
        }

my update command is:

result = collection.update_one({'_id': id}, doc)

where

id: _id of document

doc: (here) st2

collection: pymongo colllection object

The original JSON depth is 6 and the keys are dynamic. The updation will be needed at different depths.

Shipra
  • 1,259
  • 2
  • 14
  • 26
  • Possible duplicate of [How do I update a Mongo document after inserting it?](http://stackoverflow.com/questions/4372797/how-do-i-update-a-mongo-document-after-inserting-it) – jano Jun 07 '16 at 08:34
  • Another answers: http://stackoverflow.com/questions/13710770/how-to-update-values-using-pymongo – jano Jun 07 '16 at 08:40

2 Answers2

1

First, change the object to update to this:

to_update = {
   "house_no": "5102",
   "street": "Some_street",
   "city": "some_city",
   "state": "some_state"
}

And then use it to update the specific part of the document you want:

collection.update_one({_id: id}, { '$set': {"details.address2" : to_update} });
iulian
  • 5,494
  • 3
  • 29
  • 39
0

use this to add address 2:

collection.update({'_id': ObjectId(doc_id)}, {'$set': {'details.%s' % 'address2': address2}}, upsert=True)

Checkout complete code :

import pymongo
from bson.objectid import ObjectId

data = {"name": "Some_name",
       "details": {"address1": {"house_no": "731", "street": "Some_street", "city": "some_city", "state": "some_state"}}}

address2 = {"house_no": "731", "street": "Some_street", "city": "some_city", "state": "some_state"}

connect = pymongo.MongoClient('192.168.4.202', 20020)
database = connect['my_test']
collection = database['coll']

# # CREATE COLLECTIONS AND INSERT DATA
# _id = collection.insert(data)
# print _id

doc_id = '57568aa11ec52522343ee695'

collection.update({'_id': ObjectId(doc_id)}, {'$set': {'details.%s' % 'address2': address2}}, upsert=True)
Rajiv Sharma
  • 6,746
  • 1
  • 52
  • 54
  • It won't work when the keys are dynamic and at different depths. I have updated the question. – Shipra Jun 07 '16 at 10:26
  • @Shipra - your keys can be dynamic instead of "address2" variable use any key name. and if you want to go more deep than use 'details.%s.%s.%s' % ( 'var1', 'var2', 'var3'). – Rajiv Sharma Jun 07 '16 at 10:37