猫鼬Express:如何正确删除、创建和创建存储参考数据 [英] Mongoose & Express: How to properly Remove, Create & Store data that are reference

查看:30
本文介绍了猫鼬Express:如何正确删除、创建和创建存储参考数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到的第一问题是,每当我尝试删除评论时,我也会尝试在post.comments中找到该特定评论的索引在 user.comments 中,它始终返回 -1,我试图找到它的原因是这样我就可以从用户和帖子确实拥有的评论数组中拼接它.我遇到的第二问题是,每当我创建评论时,我都会尝试将其存储在用户和帖子具有的评论数组中,但它仅将其存储为字符串,尽管我认为它是应该存储为对象对吗?,所以我可以稍后通过填充来访问它?

The first problem I am having is that whenever I try to delete the Comment, I also try to find the index of that specific comment inside post.comments as well as inside user.comments, it consistently returns -1, the reason why I am trying to find it, is so that I can splice it from the comments array that user and post do have. The second problem I am having is that whenever I create a comment, I try to store it in the comments array that user and post have, but it stores it only as a string, although I think it is supposed to be stored as an object right?, So I can access it later by populating?

我已经挣扎了好几天了,因为为什么它不起作用,我感到非常沮丧.请帮帮我!

I have been struggling for days now being very frustrated why it does not work. Please help me!

下面是我删除和创建评论的两条路线,以及我的Schemas,谢谢大家的帮助!

Below will be my two routes, for deleting and creating comments, and my Schemas, Thank You for all the help!

创建评论

// @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');
    }
  }
);

删除评论

// @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);

推荐答案

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

I think you need to redesign your schemas in a simpler way, there are too many references between the models, and this causes issues, for example you have 5 db access when you want to create a comment, and 6 db access when you want to delete a comment.

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

I would create the user schema like this removing the posts and comment references, but later when we want to access the posts from users, I set up 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"
});

在帖子模式中,我删除了评论引用.(为简单起见,我删除了喜欢"和不喜欢"字段.)

And in the posts schema, I removed the comments references. (For simplicity I removed likes and dislikes fields.)

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"
});

评论模式可以保持原样.

Comment schema can stay as it is.

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

Now to add a comment to a post, we only need 2 db access, one for checking if post exists, and one for creating the post.

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 个用户:

Let's say we have these 2 users:

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

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

User1 with _id:"5e216d74e7138b638cac040d" has this post.

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

假设 user2 与 _id:"5e217192d204a26834d013e8" 对这篇文章评论了两次,如下所示:

Let's say user2 with _id:"5e217192d204a26834d013e8" commented on this post two times like this:

{
    "_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
}

要删除评论,我们可以使用以下方法,如您所见,我们将数据库访问权限从 6 减少到 3,并且代码更短更干净.

To remove a comment we can use the following route, as you see we decreased the db access from 6 to 3, and code is shorter and cleaner.

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");
  }
});

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

Now you may ask, how will access the posts from an user? Since we setup virtual populate in our user schema, we can populate the posts like this:

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

  res.send(result);
});

这篇关于猫鼬Express:如何正确删除、创建和创建存储参考数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆