0

I've looked through a bunch of other SO posts and have found different ways to do this, so I'm wondering which is most preferred. I'm teaching this to students, so I want to give them best practices.

If I have the following BlogPost object (Simplified):

var BlogPostSchema = new mongoose.Schema({
    body: String,
    comments: [String]
});

and I want to add a new comment to the array of comments for this blog, I can think of at least 3 main ways to accomplish this:

1) Push the comment to the blog object in Angular and submit a PUT request to the /blogs/:blogID endpoint, updating the whole blog object with the new comment included.

2) Submit a POST request to a /blogs/:blogID/comments endpoint where the request body is just the new comment, find the blog, push the comment to the array in vanilla js, and save it:

BlogPost.findById(req.params.blogID, function(err, blogPost) {
    blogPost.comments.push(req.body);
    blogPost.save(function(err) {
        if (err) return res.status(500).send(err);
        res.send(blogPost);
    });
});

OR

3) Submit the POST to a /blogs/:blogID/comments endpoint with the request body of the new comment, then use MongoDB's $push or $addToSet to add the commend to the array of comments:

BlogPost.findByIdAndUpdate(
    req.params.blogID,
    {$push: {comments: req.body}},
    {safe: true, new: true},
    function(err, blogPost) {
        if (err) return res.status(500).send(err);
        res.send(blogPost);
    });
});

I did find this stackoverflow post where the answerer talks about option 2 vs. option 3 and basically says to use option 2 whenever you can, which does seem simpler to me. (And I usually try to avoid methods that stop me from being able to use hooks and other mongoose goodies.)

What do you think? Any advice?

Community
  • 1
  • 1
bobbyz
  • 4,946
  • 3
  • 31
  • 42
  • I would go with option 3. Both 2 and 3 are basically the same. Option 3 does the findAndUpdate server side (resulting in 1 call to the server which returns the updated document). Where in option 2 you first retrieve the blogPost and then send the update to the server (the .save action) which are 2 calls to the server. – HoefMeistert Nov 11 '16 at 23:49

1 Answers1

1

From application point of view, point 3 is better. The reason I think are.

  1. The query itself specifies what we are trying to achieve. it's easily readable.
  2. save function is a wild card, so we don't know what it's going to change.
  3. if you fetch the document and manipulate it and then call save it, there is outside but real chance that you might mess up some other field of the document in process of manipulation unintentionally, not the case with point 3.
  4. In case of addToSet,basically the previous point is more visible.
  5. Think about the concurrency, if multiple calls comes with different comment for same blog and you are trying option 2, there is a chance that you might override the changes which were done in between you fetched the document and when you are saving it. Option 3 is better in that sense.

Performance wise they both do the same thing, so there might not be much or any visible difference. But option 3 is bit safer and cleaner.

Rahul Kumar
  • 2,781
  • 1
  • 21
  • 29
  • I guess my only concern is if I need to use a pre- or post-save, etc. hook with mongoose, then the `findByIdAndUpdate` method won't let me do that. But maybe I write it this way for now, and then if I find a need for a pre- or post- hook of some kind I'll switch it over. Thanks for the thoughts! – bobbyz Nov 14 '16 at 23:10