共计 2231 个字符,预计需要花费 6 分钟才能阅读完成。
最近,闲着没事,又把上个月写得代码拿出来了,随便完善一下没完成的评论的路由接口。
评论应该是在整个博客数据存储中,模型最为复杂的一部分了。首先要考虑的是和文章进行关联。这个可以用 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
,这是第一条评论,如果该评论下存在一条回复,则回复的 key
为 11#001#001
,下层亦是如此。使用该命名方式可以容纳的每条评论的回复量为 999,可以根据需求调整 0 的数量。
设定 Key 的意义
在建立记录的时候就把后期需要用到的 slug 直接生成,方便了前端的调用。这是一个原因。当然这不是重点,通过层次命名的 key,对删除父评论相当方便。例如下图所示的关系层级。
然后删除 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