0

suppose we have the following document:

{ '_id': 1, 'Name': 'Document1', 'Data': { 'Color': 'Green', 'Size': 5 } }

And we want to update the document using Pymongo using a dict as source. For instance, let's suppose that this is the dict we want to use to update the document:

dict1 = { 'Name': 'Document1', 'Data': { 'Size': 5 } }

If we know for sure which are the fields contained in dict1 we could use:

collection.update_one( { 'Name': dict1['Name'] }, { '$set': { 'Data.Size': dict1['Data']['Size'] } })

In the general case in which we don't know what is inside the ['Data'] field of dict1, the following approach:

collection.update_one( { 'Name': dict1['Name'] }, { '$set': { 'Data': dict1['Data'] } })

Will potentially delete any fields which were present in the document but are not in dict1 (in our example, 'Color').

Is it possible to tell Pymongo that we want to update a field (which is containing many fields) but only inserting/updating fields in the source dict?

espogian
  • 607
  • 8
  • 23

1 Answers1

0

You have to use the aggregation flavour of $set (aka $addFields) to achieve this:

from pymongo import MongoClient

db = MongoClient()['mydatabase']
collection = db.mycollection

collection.insert_one({'_id': 1, 'Name': 'Document1', 'Data': {'Color': 'Green', 'Size': 5}})
dict1 = {'Name': 'Document1', 'Data': {'Size': 6, 'Fitting': 'Wide'}}

collection.update_many({'Name': dict1.get('Name')}, [{'$addFields': {'Data': dict1.get('Data')}}])

print(collection.find_one())

prints:

{'_id': 1, 'Name': 'Document1', 'Data': {'Color': 'Green', 'Size': 6, 'Fitting': 'Wide'}}
Belly Buster
  • 8,224
  • 2
  • 7
  • 20
  • This is not working if dict1 contains some values with void dicts inside (e.g. dict1 = {'Name': 'Document1', 'Data': {}}). To avoid errors, I've implemented a cleaning stage in order to remove values = {} following the approach mentioned here: https://stackoverflow.com/questions/3405715/elegant-way-to-remove-fields-from-nested-dictionaries – espogian Jan 04 '23 at 13:16