Search code examples
mongodbmongoosemongoose-schema

Using mongoose lean after saving


So I am trying to add a key to a returned post. But I can't seem to get lean() to work. How can I manipulate the returned post after save?

I was thinking maybe I need to add lean to my findById like this Post.findById(req.params.id).lean().then(). But that didn't work, plus that only makes the first initial post mutable. It will say

post.save is not a function

if I do it like Post.findById(req.params.id).lean().then() as well

I want to only return the object about to be sent back to the client, I do not want they key saved in the actual document.

 Post.findById(req.params.id)
      .then(post => {
        if (
          post.likes.filter(like => like.user.toString() === req.user.id)
            .length === 0
        ) {
          return res
            .status(400)
            .json({ notliked: "You have not yet liked this post" });
        }

        // Get remove index
        const removeIndex = post.likes
          .map(item => item.user.toString())
          .indexOf(req.user.id);

        // Splice out of array
        post.likes.splice(removeIndex, 1);

        // Save
        post.save().then(post => {  
          post["liked"] = false;  <-------
          res.json(post);
        });
      })

edit

  Post.findById(req.params.id)
      .lean()
      .then(post => {
        if (
          post.likes.filter(like => like.user.toString() === req.user.id)
            .length === 0
        ) {
          return res
            .status(400)
            .json({ notliked: "You have not yet liked this post" });
        }

        // Get remove index
        const removeIndex = post.likes
          .map(item => item.user.toString())
          .indexOf(req.user.id);

        // Splice out of array
        post.likes.splice(removeIndex, 1);
        post["liked"] = false;
        res.json(post);
        // Save
        post.save();
      })

gives error

post.save is not a function


Solution

  • You can simply do this by searching for the req.user.id inside the indexOf likes array

    Post.findOne({ _id: req.params.id }).lean().then((post) => {
      if (post.likes.indexOf(req.user.id) !== -1) {
        post.isLiked = true
      }
      post.isLiked = false
      res.json(post)
    })
    

    Far better with the aggregation

    Post.aggregate([
      { "$match": { "_id": mongoose.Types.ObjectId(req.user.id) }},
      { "$addFields": {
        "isLiked": { "$in": [mongoose.Types.ObjectId(req.user.id), "$likes"] }
      }}
    ])
    

    EDIT :- If you want to update document then use update query

    Post.findOneAndUpdate(
      { _id: req.params.id },
      { $pull: { likes: { user: req.user.id } }},
      { new: true }
    ).then((post) => {
      res.json(post)
    })
    

    Post Schema for likes

    ...
        likes: [
            {
              user: {
                type: Schema.Types.ObjectId,
                ref: "users"
              }
            }
          ]
    ...