Pymongo update_one() issue with embedded documents

Folks:

I have a MongoDB database application with a Python Flask front end using pymongo. I am having difficulty updating only the embedded document within a collection. I have no issues updating the entire collection from an HTML form.

For example, I have no issues with:

db.polymers.update_one({ “_id”: polymer_id}, {"$set": {“name”: name, “composition”: {“monomer01”: monomer01, “monomer02”: monomer02, “mw”: 10000 }, … “comments”: comments}})

However, trying to update only one element within the embedded document named “composition” doesn’t update as expected. And there isn’t even an error message. Here is the statement:

db.polymers.update_one({"_id": polymer_id},{"$set": {“composition”: {“mw”: 15000}}})

I would appreciate any help! Thanks!

Mike.

Hi @Michael_Redlich, welcome back again to our forums. We’ve restructured these slightly since your last visit.

In general, this question might be better asked in one of the forums related to the Drivers or to Working with Data topic.

That said, it looks like there might be a quick solution to your problem.

In terms of updating a single element in array, you should use dot notation which allows the updating of a specific field in an embedded document or position within an array in your document. Checkout the $set page in the MongoDB Manual -

Have you tried using dot notation and an update_one statement of the format “composition.mv”?

db.polymers.update_one({"_id": polymer_id},{"$set": {“composition.mw”: 15000}})

Welcome back and hope this helps - if you have any questions or feedback related to M220P we’d love to hear it here, in this topic of our forums.

Kindest regards,
Eoin

Hi Eoin:

Thanks for the update on how I should submit questions related to mine. Thanks, too, for the suggested fix. I tried it, but unfortunately, the problem still exists. My other Python methods don’t behave this way.

I used the mongo shell to update this manually and all worked well. Interestingly, using the dot notation in the shell updated the element in the embedded document. Using the additional curly braces, however, updated the element and wiped out the remaining elements in the embedded document.

Hi @Michael_Redlich,

I can’t say why this would work in the shell and not with PyMongo, but I can explain the difference between the two $set commands:

{"$set": {“composition”: {“mw”: 15000}}}

This command says “Set composition to this object {“mw”: 15000}.” As you’ve seen, this will wipe out any other values stored in the composition field, because you’re not updating it, you’re replacing it with a new subdocument.

{"$set": {“composition.mw”: 15000}}

This command reads as “update the value of the mw field within the composition field to 15000.” As you’ve seen, it doesn’t affect any other values within composition, it just updates mw.

There’s no reason this should work for you in the shell, but not with PyMongo. I hate to suggest it, but I suspect the difference is either a typo in your exact update command, an incorrect filter being provided to update_one, or maybe executing the query on the wrong collection? I’ve done all of these things, so I’m only suggesting them as things to think about!

3 Likes

Hi Mark:

Thanks for all the info. I certainly appreciate it! And, yes, I’ve been bitten by typos in the past as well. I’m certain everything is correct, but I will quadruple check!

All the best,

Mike.

Hi Mark:

Just to close out this issue, I discovered that I didn’t wrap the polymer_id variable with ObjectId(). Problem solved!

Thanks to everyone who chimed-in on this issue!

Mike.