Search code examples
databasemongodbtree

Updating an element with a given field within a tree-like structure in mongodb


For example, when I have a comment structure looking like that within a single collection entry:

"comments": [
    {
        "id": 0,
        "comments": []
    },
    {
        "id": 1,
        "comments": [
            {
                "id": 3,
                "comments": [
                    {
                        "id": 5,
                        "comments": []
                    },
                    {
                        "id": 6,
                        "comments": []
                    }
                ]
            }
        ]
    },
    {
        "id": 2,
        "comments": [
            {
                "id": 4,
                "comments": []
            }
        ]
    }
]

Is there a nice way to push another comment to a comment with a given id value?


Solution

  • This structure is quite complex to query/update dynamically due to the recursive nature of the schema.

    There is no "easy" way to achieve what you're asking for without knowing the "depth" of the message, What I recommend if you want to keep the current structure is to add a new field to each message called "depth", by knowing this ahead of time it will be easier to generate a query on the fly to update the right message, like so:

    const depth = 2
    const id = 5
    
    const queryKey = `${Array(depth + 1).join('comments.')}id`;
    const query = {
        [queryKey]: id
    };
    const updateKey = `${Array(depth + 1).join('comments.$')}[elem].comments`;
    
    db.collection.updateOne(
        query,
        {
          "$push": {
            [updateKey]: {
              id: "newId",
              depth: depth + 1,
              comments: []
            }
          }
        },
        {
          arrayFilters: [
            {
              "elem.id": id
            }
          ]
        })
    

    This will dynamically generate the proper query to update the correct subdocument.

    Mongo Playground