【问题标题】:Mongoose & Express: How to properly Remove, Create & Store data that are referenceMongoose 和 Express:如何正确删除、创建和存储引用的数据
【发布时间】:2020-05-03 23:30:35
【问题描述】:

我遇到的第一个问题是,每当我尝试删除评论时,我也会尝试在 post.cmets 中找到该特定评论的索引在 user.cmets 内部,它始终返回 -1,我之所以试图找到它,是为了让我可以从用户和帖子所拥有的 cmets 数组中拼接它。 我遇到的 second 问题是,每当我创建评论时,我都会尝试将其存储在用户和帖子拥有的 cmets 数组中,但它仅将其存储为字符串,尽管我认为它是应该存储为对象吧?,所以我以后可以通过填充来访问它?

我已经挣扎了好几天了,现在很沮丧为什么它不起作用。请帮帮我!

以下将是我的两条路线,用于删除和创建 cmets,以及我的 Schema,谢谢大家的帮助!

创建评论

// @route    POST api/posts/comment/:id
// @desc     Comment on a post
// @access   Private
router.post(
  '/comment/:id',
  [
    auth,
    [
      check('text', 'Text is required')
        .not()
        .isEmpty()
    ]
  ],
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    try {
      const post = await Post.findById(req.params.id);
      const user = await User.findById(req.user.id)
      const newComment = {
        text: req.body.text,
        post: post._id,
        user: req.user.id
      };
      const comment = new Comment(newComment);
      post.comments.unshift(comment._id);
      user.comments.unshift(comment._id)
      console.log(user.comments);
      console.log(post.comments);
      console.log(comment)
      await post.save();
      await comment.save();
      await user.save();
      res.json(comment);
    } catch (err) {
      console.error(err.message);
      res.status(500).send('Server Error');
    }
  }
);

删除 cmets

// @route    DELETE api/posts/comment/:id/:comment_id
// @desc     Delete comment
// @access   Private
router.delete('/comment/:id/:comment_id', auth, async (req, res) => {
  try {
    const post = await Post.findById(req.params.id);
    const user = await User.findById(req.user.id);

    // Pull out comment by finding it through its id
    const comment = await Comment.findById(req.params.comment_id);

    // Make sure comment exists
    if (!comment) {
      return res.status(404).json({ msg: 'Post do not have this comment' });
    }

    // Check user
    if (comment.user.toString() !== req.user.id) {
      return res.status(401).json({ msg: 'User not authorized' });
    }

      // Get The value to be removed
      const postCommentIndex = post.comments.findIndex(postComment => postComment === comment._id);


      const userCommentIndex = user.comments.findIndex(userComment => userComment === comment._id);

      console.log(`This is the post comment index ${postCommentIndex}`);
      console.log(`This is the user comment index ${userCommentIndex}`);

      post.comments.splice(postCommentIndex, 1);
      user.comments.splice(userCommentIndex, 1);

    // save user and post
    await post.save();
    await user.save();
    await comment.remove();

    // resend the comments that belongs to that post
    res.json(post.comments);
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server Error');
  }
});

架构:

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true,
    unique: true
  },
  password: {
    type: String,
    required: true
  },
  avatar: {
    type: String
  },
  posts: [{type: mongoose.Schema.Types.ObjectId, ref: "Post"}],
  comments: [{type: mongoose.Schema.Types.ObjectId, ref: "Comment"}],
  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = mongoose.model('User', UserSchema);
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const PostSchema = new Schema({
  user: {
    type: Schema.Types.ObjectId,
    ref: 'User'
  },
  text: {
    type: String,
    required: true
  },
  likes: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: 'User'
      }
    }
  ],
  dislikes: [
    {
        user: {
            type: Schema.Types.ObjectId,
            ref: "User"
        }
    }
  ],
  comments: [{type: Schema.Types.ObjectId, ref: "Comment"}],
  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = mongoose.model('Post', PostSchema);
const mongoose = require("mongoose")
const Schema = mongoose.Schema;


const CommentSchema = new Schema({
        user: {
            type: Schema.Types.ObjectId,
            ref: 'User'
        },
        post: {
            type: Schema.Types.ObjectId,
            ref: "Post"
        },
        text: {
            type: String,
            required: true
        },
        date: {
            type: Date,
            default: Date.now
        }
})

module.exports = mongoose.model("Comment", CommentSchema);

【问题讨论】:

    标签: javascript node.js mongodb express mongoose


    【解决方案1】:

    你可以试试这段代码:

    Comment.deleteOne({
    _id: comment.id
    }, function (err) {
    if (err) {
      console.log(err);
      return res.send(err.message);
    }
    res.send('success');
    });
    

    【讨论】:

      【解决方案2】:

      我认为您需要以更简单的方式重新设计架构,模型之间的引用过多,这会导致问题,例如,当您想要创建评论时,您有 5 db 访问权限,而当您想要创建评论时,您有 6 db 访问权限你想删除评论。

      我会像这样创建用户架构,删除帖子和评论引用,但后来当我们想要访问用户的帖子时,我设置了virtual populate.

      const UserSchema = new Schema(
        {
          name: {
            type: String,
            required: true
          },
          email: {
            type: String,
            required: true,
            unique: true
          },
          password: {
            type: String,
            required: true
          },
          avatar: {
            type: String
          },
          date: {
            type: Date,
            default: Date.now
          }
        },
        {
          toJSON: { virtuals: true }
        }
      );
      
      UserSchema.virtual("posts", {
        ref: "Post",
        localField: "_id",
        foreignField: "user"
      });
      

      在帖子架构中,我删除了 cmets 引用。 (为简单起见,我删除了喜欢和不喜欢的字段。)

      const PostSchema = new Schema(
        {
          user: {
            type: Schema.Types.ObjectId,
            ref: "User"
          },
          text: {
            type: String,
            required: true
          },
          date: {
            type: Date,
            default: Date.now
          }
        },
        {
          toJSON: { virtuals: true }
        }
      );
      
      PostSchema.virtual("comments", {
        ref: "Comment",
        localField: "_id",
        foreignField: "post"
      });
      

      评论模式可以保持原样。

      现在要为帖子添加评论,我们只需要 2 个数据库访问权限,一个用于检查帖子是否存在,一个用于创建帖子。

      router.post(
        "/comment/:id",
        [
          auth,
          [
            check("text", "Text is required")
              .not()
              .isEmpty()
          ]
        ],
        async (req, res) => {
          const errors = validationResult(req);
          if (!errors.isEmpty()) {
            return res.status(400).json({ errors: errors.array() });
          }
      
          try {
            const post = await Post.findById(req.params.id);
            if (!post) {
              return res.status(404).json({ msg: "Post not found" });
            }
      
            let comment = new Comment({
              text: req.body.text,
              post: req.params.id,
              user: req.user.id
            });
      
            comment = await comment.save();
      
            res.json(comment);
          } catch (err) {
            console.error(err.message);
            res.status(500).send("Server Error");
          }
        }
      );
      

      假设我们有这 2 个用户:

      {
          "_id" : ObjectId("5e216d74e7138b638cac040d"),
          "name" : "user1"
      }
      {
          "_id" : ObjectId("5e217192d204a26834d013e8"),
          "name" : "user2"
      }
      

      _id:"5e216d74e7138b638cac040d" 的用户 1 有此帖子。

      {
          "_id": "5e2170e7d204a26834d013e6",
          "user": "5e216d74e7138b638cac040d",
          "text": "Post 1",
          "date": "2020-01-17T08:31:35.699Z",
          "__v": 0,
          "id": "5e2170e7d204a26834d013e6"
      }
      

      假设 _id:"5e217192d204a26834d013e8" 的用户 2 对这篇文章发表了两次这样的评论:

      {
          "_id" : ObjectId("5e2172a4957c02689c9840d6"),
          "text" : "User2 commented on user1 post1",
          "post" : ObjectId("5e2170e7d204a26834d013e6"),
          "user" : ObjectId("5e217192d204a26834d013e8"),
          "date" : ISODate("2020-01-17T11:39:00.396+03:00"),
          "__v" : 0
      },
      {
          "_id": "5e21730d468bbb7ce8060ace",
          "text": "User2 commented again on user1 post1",
          "post": "5e2170e7d204a26834d013e6",
          "user": "5e217192d204a26834d013e8",
          "date": "2020-01-17T08:40:45.997Z",
          "__v": 0
      }
      

      要删除评论,我们可以使用以下路线,如您所见,我们将 db 访问权限从 6 减少到 3,并且代码更短更清晰。

      router.delete("/comment/:id/:comment_id", auth, async (req, res) => {
        try {
          const comment = await Comment.findById(req.params.comment_id);
      
          if (!comment) {
            return res.status(404).json({ msg: "Post do not have this comment" });
          }
      
          if (comment.user.toString() !== req.user.id) {
            return res.status(401).json({ msg: "User not authorized" });
          }
      
          await comment.remove();
      
          // resend the comments that belongs to that post
          const postComments = await Comment.find({ post: req.params.id });
          res.json(postComments);
        } catch (err) {
          console.error(err.message);
          res.status(500).send("Server Error");
        }
      });
      

      现在您可能会问,如何访问用户的帖子?由于我们在用户模式中设置了虚拟填充,我们可以像这样填充帖子:

      router.get("/users/:id/posts", async (req, res) => {
        const result = await User.findById(req.params.id).populate("posts");
      
        res.send(result);
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 2021-12-20
        • 2016-02-26
        • 1970-01-01
        • 2014-05-27
        • 2014-09-17
        • 2012-07-23
        相关资源
        最近更新 更多