最近,闲着没事,又把上个月写得代码拿出来了,随便完善一下没完成的评论的路由接口。
评论应该是在整个博客数据存储中,模型最为复杂的一部分了。首先要考虑的是和文章进行关联。这个可以用 mongoDB 的 ref
进行关联,随后可以使用 populate
计算出被关联的字段。
最后关系复杂的是父子层级的评论,又或者是多级评论。这个时候就要想该怎么做才能合理的管理这些层级关系,在删除父评论的同时又能把所有子评论一起删除。查询的时候如何去由根到叶顺序输出层级关系。
js
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
,这是第一条评论,如果该评论下存在一条回复,则回复的 key
为 11#001#001
,下层亦是如此。使用该命名方式可以容纳的每条评论的回复量为 999,可以根据需求调整0的数量。
在建立记录的时候就把后期需要用到的slug直接生成,方便了前端的调用。这是一个原因。当然这不是重点,通过层次命名的 key,对删除父评论相当方便。例如下图所示的关系层级。
然后删除 key 为 11#001
的评论只要使用正则匹配 /^11#001/
即可,把匹配到的内容全部删除就可以不用管关联的 post
是否一致,以及 cid
,而 key
的值可以从前端发起的请求中提取 cid
,用 cid
去查这个唯一记录,从中拿到我们需要的 key。
参考删除评论路由如下
js
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
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
最后,看看数据库中的记录如何。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有