前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >对博客中评论的合理建模 --MongoDB

对博客中评论的合理建模 --MongoDB

作者头像
Innei
发布2021-12-28 11:42:31
5250
发布2021-12-28 11:42:31
举报
文章被收录于专栏:静之森静之森

最近,闲着没事,又把上个月写得代码拿出来了,随便完善一下没完成的评论的路由接口。

评论应该是在整个博客数据存储中,模型最为复杂的一部分了。首先要考虑的是和文章进行关联。这个可以用 mongoDB 的 ref 进行关联,随后可以使用 populate 计算出被关联的字段。

最后关系复杂的是父子层级的评论,又或者是多级评论。这个时候就要想该怎么做才能合理的管理这些层级关系,在删除父评论的同时又能把所有子评论一起删除。查询的时候如何去由根到叶顺序输出层级关系。

建立评论模型

js

代码语言:javascript
复制
1const schema = new mongoose.Schema({
2  // comment id
3  cid: {
4    type: Number,
5    required: true,
6    unique: true
7  },
8  // post id
9  pid: {
10    type: Number,
11    required: true
12  },
13  post: {
14    type: mongoose.SchemaTypes.ObjectId,
15    ref: 'Post'
16  },
17  content: {
18    type: String,
19    required: true
20  },
21  createTime: {
22    type: Number,
23    default: Date.now()
24  },
25  author: {
26    type: String,
27    required: true
28  },
29  owner: {
30    type: String,
31    required: true
32  },
33  isOwner: {
34    type: Boolean,
35    required: true
36  },
37  email: {
38    type: String
39  },
40  url: {
41    type: String
42  },
43  key: {
44    type: String,
45    required: true,
46    unique: true
47  },
48  parent: {
49    type: mongoose.SchemaTypes.ObjectId,
50    ref: 'Comment'
51  },
52  hasChild: { type: Boolean, default: false },
53  ipAddress: {
54    type: String,
55    required: true
56  },
57  userAgent: {
58    type: String
59  },
60  // 0 审核 1 发布 2 垃圾
61  state: {
62    type: Number,
63    required: true,
64    default: 0
65  }
66})

COPY

在模型中,post列中关联引用表(post表)的 _id(文章),在 hasChild 中记录是否存在回复。在后期处理回复路由的时候不要忘记修改他的值。最关键的是 key 列,这个用来记录平行层级。如 post 中的一篇 pid 为 11 的文章下有一条评论,那么 key 中命名 11#001,这是第一条评论,如果该评论下存在一条回复,则回复的 key11#001#001,下层亦是如此。使用该命名方式可以容纳的每条评论的回复量为 999,可以根据需求调整0的数量。

设定 Key 的意义

在建立记录的时候就把后期需要用到的slug直接生成,方便了前端的调用。这是一个原因。当然这不是重点,通过层次命名的 key,对删除父评论相当方便。例如下图所示的关系层级。

https://cdn.jsdelivr.net/gh/innei/img-bed@master/20191013202521.png
https://cdn.jsdelivr.net/gh/innei/img-bed@master/20191013202521.png

然后删除 key 为 11#001 的评论只要使用正则匹配 /^11#001/即可,把匹配到的内容全部删除就可以不用管关联的 post 是否一致,以及 cid,而 key 的值可以从前端发起的请求中提取 cid,用 cid 去查这个唯一记录,从中拿到我们需要的 key。

参考删除评论路由如下

js

代码语言:javascript
复制
1router.delete('/', async (req, res) => {
2  const id = req.query.id
3  if (id) {
4    const isCid = id.length !== 24 ? true : false
5    try {
6      const query = await Comment.findOneAndDelete({
7        cid: id
8      }).populate('post')
9      if (query) {
10        if (query.hasChild) {
11          const delCount =
12          (await Comment.deleteMany({
13            key: new RegExp(`^${query.key}`, 'ig')
14          })).deletedCount + 1
15        }
16        await User.updateOne(
17        { username: req.username },
18        {
19          $inc: {
20            'options.comments_nums': -(delCount || 1)
21          }
22        }
23        )
24          // 删除post中的comments数量
25          query.post.comments -= delCount || 1
26          await query.post.save()
27}
28
29return res.send({ ok: 1, n: 1, deleteCount: delCount || 1 })
30} catch (e) {
31  console.log(e)
32  return res.send({ ok: 0, msg: '参数不正确' })
33}
34}
35return res.send({ ok: 0, msg: '请输入正确的ID' })
36})

COPY

说完了删除,相比之下新建评论就容易多了,只要根据原本的评论数量设定新的 key 就行了。可以使用模型提供的方法 countDocument()

js

代码语言:javascript
复制
1const body = req.body
2const comments = await Comment.countDocuments({
3      pid,
4      key: new RegExp(`^${pid}#\\d\\d\\d$`)
5    })
6body.key = String(pid) + `#${String(comments + 1).padStart(3, 0)}`

COPY

最后,看看数据库中的记录如何。

https://raw.githubusercontent.com/Innei/img-bed/master/20191013204019.png
https://raw.githubusercontent.com/Innei/img-bed/master/20191013204019.png

接口测试

https://raw.githubusercontent.com/Innei/img-bed/master/20191013204208.png
https://raw.githubusercontent.com/Innei/img-bed/master/20191013204208.png
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-10-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 建立评论模型
  • 设定 Key 的意义
  • 接口测试
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档