简体   繁体   English

帖子、评论和回复的数据库架构设计

[英]Database schema design for posts, comments and replies

In my previous project I had posts and comments as two tables:在我之前的项目中,我将帖子和评论作为两个表格:

post发帖

  • id身份证
  • text文字
  • timestamp时间戳
  • userid用户名

comment评论

  • id身份证
  • message留言
  • timestamp时间戳
  • userid用户名
  • postid postid

Now I've got to design replies to comments.现在我必须设计对评论的回复。 The replies is just one level, so users can only reply to comments, not to replies.回复只是一层,所以用户只能回复评论,不能回复。 The tree structure is only 1 level deep.树结构只有 1 级深。 My first idea was to use the same comment table for both comments and replies.我的第一个想法是对评论和回复使用相同的评论表。 I added a new column though:不过,我添加了一个新列:

comment评论

  • id身份证
  • message留言
  • timestamp时间戳
  • userid用户名
  • postid postid
  • parentcommentid家长评论

Replies have parentcommentid set to the parent comment they belong.回复将 parentcommentid 设置为它们所属的父评论。 Parent comments don't have it (null)父评论没有它(空)

Retrieving comments for a given post is simple:检索给定帖子的评论很简单:

but this time I need another query to find out the comment replies.但这次我需要另一个查询来找出评论回复。 This has to be done for each comment:必须为每个评论执行此操作:

This doesn't seem to be a good solution, is there a way to have a single query which returns the complete list of comments/replies in the correct order?这似乎不是一个好的解决方案,有没有办法让单个查询以正确的顺序返回完整的评论/回复列表? (dictated by the timestamp and the nesting) (由时间戳和嵌套决定)

You may use join and achieve result in single query like I provided below:您可以使用 join 并在单个查询中获得结果,如下所示:

  SELECT *, cc.message as replied_message 
    FROM `post` 
    JOIN comment as c 
      ON c.postid = post.id 
    JOIN comment as cc 
      ON cc.id = c.parentcommentid 
ORDER BY c.timestamp DESC, cc.timestamp DESC;

Please note that, it works correctly only if 1 comment have 1 reply only.multiple replies on single comment will not support by this query请注意,只有 1 条评论只有 1 条回复才能正常工作。此查询不支持对单个评论的多个回复

If you're using a database that supports JSON or object aggregation, you can get a nicer result from the query where each top-level comment is a row (and is not duplicated), and the replies are nested in an array/JSON within each row.如果您使用的是支持 JSON 或对象聚合的数据库,您可以从查询中获得更好的结果,其中每个顶级评论都是一行(并且不重复),并且回复嵌套在数组/JSON 中每行。

This gives you flexibility with what you do with it and also makes it easier to ensure the ordering and nesting is correct.这使您可以灵活地使用它,并且还可以更轻松地确保排序和嵌套正确。

An example using Postgres:一个使用 Postgres 的例子:

SELECT
  p.id AS post_id,
  c.id AS comment_id,
  c.message,
  JSON_AGG(
    JSON_BUILD_OBJECT('comment', r.comment, 'timestamp', r.timestamp)
    ORDER BY r.timestamp
  ) AS child_comments
FROM
  post AS p
  INNER JOIN comment AS c
    ON c.post_id = p.id
  LEFT JOIN comment AS r
    ON r.parent_id = c.id
WHERE
  post.id = <some id>
  AND c.parent_id IS NULL
GROUP BY
  post.id,
  c.id,
  c.message
ORDER BY
  c.timestamp DESC
;

Note that, as above, this example will only retrieve the top-level and their first-level replies.请注意,如上所述,此示例将仅检索顶级及其第一级回复。 It won't get replies to replies.它不会得到回复的回复。 You can use recursive commands or additional subqueries to do that.您可以使用递归命令或其他子查询来做到这一点。

I know this reply is years too late, but hopefully it will help others facing this problem now.我知道这个回复为时已晚,但希望它可以帮助现在面临这个问题的其他人。

I came up with single table and a single query that returns all the results in the correct order that I use on my own site, it's slightly different but the logic could be used to fit this question.我想出了一个表和一个查询,它以我在我自己的网站上使用的正确顺序返回所有结果,它略有不同,但逻辑可用于解决这个问题。

table name : comments表名:评论

  • id / varchar(32) id/varchar(32)
  • userid / int(10)用户 ID/int(10)
  • comment / text评论/文字
  • ordering / int(10)排序/整数(10)
  • ordering_secondary / int(10) ordering_secondary / int(10)
  • source / tinyint(4)源/tinyint(4)
  • state / tinyint(4)状态/tinyint(4)
  • created / timestamp创建/时间戳
  • edited / timestamp编辑/时间戳

There is a primary key on (id, ordering, ordering_secondary, source), so no duplicate of these four columns combined will insert. (id, ordering, ordering_secondary, source) 上有一个主键,因此不会插入合并的这四列的重复项。

Inserting a comment you first check "ordering" and increment the new comment by 1.插入评论时,您首先检查“排序”并将新评论增加 1。

SELECT ordering FROM comments WHERE id="page id" AND source=0 ORDER BY ordering DESC LIMIT 1

"source" column will be "0" for parent, "1" for a reply for example.例如,“源”列将为父级为“0”,为回复为“1”。 So just insert the comment with the ordering value incremented by 1 for each comment on a specific id.因此,只需为特定 id 上的每个评论插入排序值加 1 的评论。

When inserting a reply comment, use the same "ordering" value as the parent but increment the "ordering_secondary" column.插入回复评论时,使用与父级相同的“排序”值,但增加“ordering_secondary”列。

SELECT ordering FROM comments WHERE id="page id" AND source=1 AND ordering="parent comment ordering" ORDER BY ordering DESC LIMIT 1

So the data would look like :所以数据看起来像:

在此处输入图片说明

In the table there are two parent comments and two replies to the second parent comment.在表中有两个父评论和对第二个父评论的两个回复。 No replies to first parent comment.没有回复第一个家长评论。

This approach is obviously slightly more overhead on inserts as you have to look up the ordering value of the last comment on an "id" but querying the data is simple.这种方法在插入上的开销显然略高一些,因为您必须在“id”上查找最后一条评论的排序值,但查询数据很简单。

SELECT * FROM comments WHERE id=? ORDER BY ordering DESC, ordering_secondary ASC LIMIT 30

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM