简体   繁体   中英

Rename field in embedded document with PyMongo

I have a collection in mongodb and I want to rename some fields name. My collection is like:

    {
    "_id": "",
    "user": "5a02d87ac12d314721bd9a15",
    "item": {
        "5b20db50a32c0e02693ffad6": {
            "item_value": [{
                "timepstamp": "",
                "value": 0.2
            }, {
                "timepstamp": "",
                "value": 0.8
            }, {
                "timepstamp": "",
                "value": 0.9
            }]
        },
        "843ujsafu88gfs88987898f": {
            "item_value": [{
                "timepstamp": "",
                "value": 0.2
            }, {
                "timepstamp": "",
                "value": 0.8
            }, {
                "timepstamp": "",
                "value": 0.9
            }]
        }
    }
}

I want to rename the "5b20db50a32c0e02693ffad6" and "843ujsafu88gfs88987898f" which are the keys after the item with new values i have lets say "12345x" and "12345y"

How can I perform that query in pymongo? I can retrieve the value from the collection with the following code:

db = client['db']
collection = db['col']
res = collection.find({})

for item in res:
    items= item["item"]
    for key in items:
         print (key)
    ## collection.update({}, {$rename: {item["item"][key]: item["item"][new_item_id]}}, False, True)

That code return the keys that I want to rename. How can I do so?

EDIT: I tried to use the collection update and the method rename. It seems that it does not work. How can I change that field only and how I will use properly pymongo here?

EDIT2: In my case I need to do something like that:

 _id = res['_id']
 item.pop('_id')   # this is imp
 _user = item['user']
 item.pop('user')   # this is imp

 collection.update({'_id': _id, 'user': _user }, {$set: item})

To rename field in MongoDB, we usually use the $rename update operate which works beautifully with embedded document as well.

from pymongo import MongoClient


uri = mongodb://127.0.0.1:27017"

old_fields_names = ["5b20db50a32c0e02693ffad6",
                    "843ujsafu88gfs88987898f"]
new_fields_names = ["12345x", "12345y"]
with MongoClient(uri) as client:
    db = client.db
    col = db.col
    update_doc = {f"item.{old}": f"item.{new}"
                  for old, new in zip(old_fields_names, new_field_names)}
    update = {"$rename": update_doc}
    col.update_many({}, update)

Note the use of the context manager aka with statement to open the connection to the database, which ensure the connection is close when we are done with the operation to avoid leaking resources.

I think you have already come to right steps only few more steps remaining. Below will work. Also, I am assuming that you already have a mapping which key you want to replace and to what -

db = client['db']
collection = db['col']
res = collection.find({})

for doc in res:
    items= doc["item"]
    for key in items:
         # Now suppose you want to replace this key 
        if key want to replace:
             temp = copy.deepcopy(items[key])
             items["new_Key_name"] = temp
             items.pop(key)  # deleting old key with data

     # Now one document has been modified with expected key Now update the DB
     _id = copy.deepcopy(doc['_id'])
     doc.pop('_id')   # this is imp
     collection.update({'_id': _id }, {$set: doc})

Now One Suggestion in the End. Do not use above approach because there are DB Queries inside Loop which is not good. Learn about BulkWrite given in Pymongo Documentation. Its very easy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM