【模型設計】對博客中評論的合理建模 --MongoDB

最近,閒着沒事,又把上個月寫得代碼拿出來了,隨便完善一下沒完成的評論的路由接口。html

評論應該是在整個博客數據存儲中,模型最爲複雜的一部分了。首先要考慮的是和文章進行關聯。這個能夠用 mongoDB 的 ref 進行關聯,隨後可使用 populate 計算出被關聯的字段。前端

最後關係複雜的是父子層級的評論,又或者是多級評論。這個時候就要想該怎麼作才能合理的管理這些層級關係,在刪除父評論的同時又能把全部子評論一塊兒刪除。查詢的時候如何去由根到葉順序輸出層級關係。git

創建評論模型

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的數量。github

設定 Key 的意義

在創建記錄的時候就把後期須要用到的slug直接生成,方便了前端的調用。這是一個緣由。固然這不是重點,經過層次命名的 key,對刪除父評論至關方便。例以下圖所示的關係層級。數據庫

而後刪除 key 爲 11#001 的評論只要使用正則匹配 /^11#001/便可,把匹配到的內容所有刪除就能夠不用管關聯的 post 是否一致,以及 cid,而 key 的值能夠從前端發起的請求中提取 cid,用 cid 去查這個惟一記錄,從中拿到咱們須要的 key。async

參考刪除評論路由以下mongoose

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()post

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
相關文章
相關標籤/搜索