DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Update an object in nested array in MongoDB
Rajesh Royal
Rajesh Royal

Posted on • Updated on

Update an object in nested array in MongoDB

Hello Reader πŸ‘‹

To update an object inside a nested array in MongoDB you can use this approach, Its well tested and working.

Case:

Update nested array objects. See below picture for a better Idea what we are going to do. We will update the object which is nested by 3 levels of array.

{
 discussionList[
  discussionList [
   {
     object-value-to-be-updated.
   }
  ]
 ]
} 
Enter fullscreen mode Exit fullscreen mode

mongodb - update an object inside multilevel nested array

Solution:

public courseCategoryPostCommentReplyUpdate(operation: CommentReplyUpdateMutation): Promise<IDocumentUpdateType> {
    return this.courseCategoryPostCommentsModel.updateOne(
      {
        "postId" : operation.postId,
        'discussionList': {
          '$elemMatch': {
            '_id': operation.commentId,
            "discussionList._id": operation.replyId
          }
        }
      },
      {
        $set: {
          "discussionList.$[outer].discussionList.$[inner].payload": operation.payload,
          "discussionList.$[outer].discussionList.$[inner].isUpdated": true,
          "discussionList.$[outer].discussionList.$[inner].commentUpdateTime": new Date()
        }
      },
      {
        arrayFilters: [
          { "outer._id": operation.commentId},
          {"inner._id": operation.replyId}

      ]
      }
    );
  }
Enter fullscreen mode Exit fullscreen mode

FootNotes - this code is to update the reply of a comment.

That's how you can perform operations on an object in nested array in mongoDB document. You can also update/delete the objects which are having the more level of nesting by just modifying the query.

Example of delete and get

Delete
// Informational Note:
  // Delete nested array values in mongodb


  public courseCategoryPostCommentReplyDelete(operation: CommentReplyDeleteMutation): Promise<IDocumentUpdateType> {
    return this.courseCategoryPostCommentsModel.updateOne(
      {
        'postId': operation.postId,

        'discussionList': {
          '$elemMatch': {
            '_id': operation.commentId,
            'discussionList._id': operation.replyId
          }
        }
      }, {
        $pull: {
          'discussionList.$[outer].discussionList': {
            user: operation.userId,
            _id: operation.replyId
          }
        }
      },
      {
        arrayFilters: [
          { 'outer._id': operation.commentId }
        ],
        multi: false
      }
    );
  }
}

Enter fullscreen mode Exit fullscreen mode

GET

public courseCategoryPostCommentRead(postId: string): Promise<IComment> {
    return this.courseCategoryPostCommentsModel.findOne<IComment>({
      postId: postId
    }).populate('discussionList.user').populate('discussionList.discussionList.user').exec();
  }
Enter fullscreen mode Exit fullscreen mode

I was using GraphQL. You may need to iterate over the result and show the comments/replies as per that.

Please let me know if the code needs an explanation. Thanks πŸ™‚

Top comments (4)

Collapse
linkitsoftoffice profile image
linkitsoftoffice

how can I use pull in this? I tried modifying the query but it prompts me up with errors like, pull to a non array value further modifying it gives me, Could not find path "undefined.0.userId" in schema.

Collapse
rajeshroyal profile image
Rajesh Royal Author

@linkitsoftoffice I have updated the post.

Collapse
ssembara profile image
Sebastianus Sembara

where do we get the inner and outer variables?

Collapse
rajeshroyal profile image
Rajesh Royal Author • Edited on

You don't have to get those variables.

The inner and outer variables are used as placeholders. If you see in the arrayFilter we are modifying the ._id part of these variables.

🌚 Browsing with dark mode makes you a better developer.

It's a scientific fact.