mongomock
mongomock copied to clipboard
Positional $ update_one doesn't update different object levels correctly
When using the positional $ operator to update multiple properties in an array of nested objects if you supply different levels of object nesting it will only take the first level specified and applies it to all properties. Pymongo on an actual db correctly updates the object.
For example: For an original object of:
{'a_list': [{'outer_bool': False, 'outer_str': 'blah', 'inner': {'inner_bool': False, 'inner_str': 'blee'}}], '_id': ObjectId(<id>)}
With the following update_one call:
the_collection.update_one({"_id": ObjectId(<id>), "a_list.outer_str": "blah"},
{"$set": {"a_list.$.outer_bool": True, "a_list.$.outer_string": "blah_update",
"a_list.$.inner.inner_bool": True, "a_list.$.inner.inner_str": "blee_update"}})
Returns the following in mongomock:
{'a_list': [{'outer_bool': True, 'outer_str': 'blah_update', 'inner': {'inner_bool': False, 'inner_str': 'blee'}, 'inner_bool': True, 'inner_str': 'blee_update'}], '_id': ObjectId(<id>)}
And the following in pymongo:
{'_id': ObjectId(<id>), 'a_list': [{'outer_bool': True, 'outer_str': 'blah_update', 'inner': {'inner_bool': True, 'inner_str': 'blee_update'}}]}
As a workaround you can separate out the updates by level:
the_collection.update_one({"_id": ObjectId<id>), "a_list.outer_str": "blah"},
{"$set": {"a_list.$.inner.inner_bool": True, "a_list.$.inner.inner_str": "blee_update"}})
the_collection.update_one({"_id": ObjectId<id>), "a_list.outer_str": "blah"},
{"$set": {"a_list.$.outer_bool": True, "a_list.$.outer_str": "blah_update"}})