How do I push to a nested array in a PyMongo database?

Question:

I have a MongoDB database with the following structure (simplified for the question’s sake):

User:

"id": int
"aquarium": Aquarium[]

Aquarium:

"name": str
"fish": Fish[]

I have access to:

  • The database, which contains a list of objects of type User, which in turn have their own Aquarium objects (users_db)
  • The unique ID of the target User, which is supposed to be the subject of the operation (id)
  • The unique name of the Aquarium, which is supposed to be the subject of the operation (aquarium_name)
  • A Fish type object (obj)

My purpose is to push the Fish type object (refered to as "obj" in the code) into the target Aquarium’s fish array.

So far I have attempted to achieve this with the following code:

    users_db.find_one_and_update
    (
        {
            "_id": ObjectId(str(id)),
            "aquarium.name": aquarium_name
        }, 
        {
            "$push": {"aquarium.fish": obj}
        }
    )

This was, however, unsuccessful. The following error was returned:
The error displayed when the POST operation is performed

I have reviewed numerous other question, such as this one, however I could not find a question which simultaneously demands a query dependent on both the inner and outer layer and insertion into the inner layer at the same time. It is hard for me to tell whether the issue comes from an invalid query or an invalid update operation, therefore I am unsure of which direction to go from this point.

Does anybody know what could be the cause of this? I’d appreciate any help.

Asked By: Panzer

||

Answers:

You get the mentioned problem as you are trying to add an object into the fish array which is a nested array (aquarium is also an array).

You need $ operator after aquarium. Aims to update the first matched aquarium array.

MongoDB query

db.collection.update({
  "_id": ObjectId("5a934e000102030405000000"),
  "aquarium.name": "Aqua A"
},
{
  "$push": {
    "aquarium.$.fish": {
      name: "Tortoise",
      color: "Green"
    }
  }
})

Demo @ Mongo Playground

users_db.find_one_and_update
    (
        {
            "_id": ObjectId(str(id)),
            "aquarium.name": aquarium_name
        }, 
        {
            "$push": {"aquarium.$.fish": obj}
        }
    )
Answered By: Yong Shun

While Yong’s answer was very helpful and got me closer to the answer, ultimately it didn’t entirely solve my problem.

What did, however, solve my issue, was using array_filters to find the appropriate entry.

The functional code is as below:

users_db.find_one_and_update(
  {"_id": ObjectID(str(id))},
  {"$push": {"aquarium.$[a].fish": obj}},
  array_filters=[{"a.name": aquarium_name}],
)
Answered By: Panzer
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.