【模型设计】对博客中评论的合理建模 --MongoDB

多态苔藓
• 阅读 3265

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

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

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

建立评论模型

const schema = new mongoose.Schema({
  // comment id
  cid: {
    type: Number,
    required: true,
    unique: true
  },
  // post id
  pid: {
    type: Number,
    required: true
  },
  post: {
    type: mongoose.SchemaTypes.ObjectId,
    ref: 'Post'
  },
  content: {
    type: String,
    required: true
  },
  createTime: {
    type: Number,
    default: Date.now()
  },
  author: {
    type: String,
    required: true
  },
  owner: {
    type: String,
    required: true
  },
  isOwner: {
    type: Boolean,
    required: true
  },
  email: {
    type: String
  },
  url: {
    type: String
  },
  key: {
    type: String,
    required: true,
    unique: true
  },
  parent: {
    type: mongoose.SchemaTypes.ObjectId,
    ref: 'Comment'
  },
  hasChild: { type: Boolean, default: false },
  ipAddress: {
    type: String,
    required: true
  },
  userAgent: {
    type: String
  },
  // 0 审核 1 发布 2 垃圾
  state: {
    type: Number,
    required: true,
    default: 0
  }
})

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

设定 Key 的意义

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

【模型设计】对博客中评论的合理建模 --MongoDB

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

参考删除评论路由如下

router.delete('/', async (req, res) => {
  const id = req.query.id
  if (id) {
    const isCid = id.length !== 24 ? true : false
    try {
      const query = await Comment.findOneAndDelete({
        cid: id
      }).populate('post')
      if (query) {
        if (query.hasChild) {
          const delCount =
          (await Comment.deleteMany({
            key: new RegExp(`^${query.key}`, 'ig')
          })).deletedCount + 1
        }
        await User.updateOne(
        { username: req.username },
        {
          $inc: {
            'options.comments_nums': -(delCount || 1)
          }
        }
        )
          // 删除post中的comments数量
          query.post.comments -= delCount || 1
          await query.post.save()
}

return res.send({ ok: 1, n: 1, deleteCount: delCount || 1 })
} catch (e) {
  console.log(e)
  return res.send({ ok: 0, msg: '参数不正确' })
}
}
return res.send({ ok: 0, msg: '请输入正确的ID' })
})

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

const body = req.body
const comments = await Comment.countDocuments({
      pid,
      key: new RegExp(`^${pid}#\\d\\d\\d$`)
    })
body.key = String(pid) + `#${String(comments + 1).padStart(3, 0)}`

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

【模型设计】对博客中评论的合理建模 --MongoDB

接口测试

【模型设计】对博客中评论的合理建模 --MongoDB

初心者,一起学习,欢迎指出不足。
转载于我的博客 对博客中评论的合理建模 --MongoDB
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
4年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
4年前
ThinkPHP 根据关联数据查询 hasWhere 的使用实例
很多时候,模型关联后需要根据关联的模型做查询。场景:广告表(ad),广告类型表(ad\_type),现在需要筛选出广告类型表中id字段为1且广告表中status为1的列表先看关联的设置部分 publicfunctionadType(){return$thisbelongsTo('A
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
2年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这