DEV Community

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

Posted on • Edited 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 (6)

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

@linkitsoftoffice I have updated the post.

Collapse
 
saheb24027824 profile image
Uifoxes

Data :

[ { _id: ObjectId("641050763af868f204dd3ce6"), username: 'erkin', email: 'erkin-07@hotmail.com', password: 'b', playlists: [ { _id: 58, name: 'asdsa', date: '09-01-15', musics: [ { name: 'INNA - Cola Song (feat. J Balvin)', duration: '3.00' }, { name: 'blabla', duration: '3.00' }, { name: 'new', duration: '3.00' } ] } ] } ] 
Enter fullscreen mode Exit fullscreen mode

Query

db.test.updateOne( { username: 'erkin', playlists:{$elemMatch: {name:"asdsa" , "musics.name":"blabla"}} }, { $set:{"playlists.$[outer].musics.$[inner].duration":"4.00"} }, { $arrayFilters:[{"outer.name":"asdsa"},{"inner.name":"blabla"}] } ) 
Enter fullscreen mode Exit fullscreen mode

Output
MongoServerError: No array filter found for identifier 'outer' in path 'playlists.$[outer].musics.$[inner].duration'

Please help to correct the error

Collapse
 
ssembara profile image
Sebastianus Sembara

where do we get the inner and outer variables?

Collapse
 
rajeshroyal profile image
Rajesh Royal • Edited

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.

Collapse
 
saheb24027824 profile image
Uifoxes

found the issue $arrayFilters , it should be arrayFilters