0

I want to update a comment in a post. I first retrieve the post document which looks like this.

{
    "_id" : ObjectId("5aac169c229f0136296407d4"),
    "title" : "First Node.js App",
    "body" : "testing 123",
    "status" : "public",
    "user" : "John Doe",
    "date" : ISODate("2017-12-21T18:30:09.779Z"),
    "comments" : [ 
        {
            "commentBody" : "This is awesome! ",
            "commentUser" : ObjectId("5a3bfd5a9e65351f9c18ba18"),
            "_id" : ObjectId("5a3c02379e65351f9c18ba1a"),
            "commentDate" : ISODate("2017-12-21T18:49:27.620Z")
        },
        {
            "commentBody" : "This is second comment.",
            "commentUser" : ObjectId("5a3bfd5a9e65351f9c18gt19"),
            "_id" : ObjectId("5a3c02379e65351f9c18ba1b"),
            "commentDate" : ISODate("2017-12-21T18:49:27.620Z")
        }
    ],
    "allowComments" : true
}

Let say I want to update comment with "_id" ObjectId("5a3c02379e65351f9c18ba1a").

I've tried the following without luck.

const post = await Post.findById(req.body.postID);

await post.update({'comments._id' : req.body.commentID},{$set : {
  'comments.$.commentBody': req.body.comment
  }
});

This gave me the following error: MongoError: cannot use the part (comments of comments._id) to traverse the element

Any suggestion would be greatly appreciated. Thanks in advance!

user752746
  • 617
  • 9
  • 31

2 Answers2

1

You can try something like this::

Post.findOneAndUpdate(
{ "_id": req.body.postID, "comments._id": req.body.commentID },
    { 
        "$set": {
            'comments.$.commentBody': req.body.comment
        }
    },
    function(err,doc) {

    }
);
user752746
  • 617
  • 9
  • 31
Akshansh Thakur
  • 5,163
  • 2
  • 21
  • 38
0

I'm not sure about how to implement this in node.js but here is the Mongo query:

db.sample.aggregate([
{$match:{"comments.commentUser":ObjectId("5a3bfd5a9e65351f9c18ba19")}},
{$redact:{
     $cond:{
       if:{$or:[{$eq:["$commentUser",ObjectId("5a3bfd5a9e65351f9c18ba19")]}, 
{$not:"$commentUser"}]},
     then:"$$DESCEND",
     else:"$$PRUNE"
    }

}},
  {$addFields:{comments:{$map:{
                     input:"$comments",
                     as:"comment",
                     in:{"commentBody":"test comment", "commentUser" : "$$comment.commentUser", "_id" :"$$comment._id", "commentDate" :"$$comment.commentDate"}

    }}

   }},
   {$out:"sample"} 
])

Restricted the document such that only particular user id comments are displayed. After that, added comments with updated comment. Finally replacing the original content within aggregation without update query(note that collection will get replaced if you run the query). I didnt test this extensively, but working for small data set in my local. However, you might need to add some tweaks to this query and then check how u can add same query to node.js

Rahul Raj
  • 3,197
  • 5
  • 35
  • 55