【问题标题】:Proper Data Structure for Commentable Comments可评论评论的正确数据结构
【发布时间】:2012-08-23 09:21:46
【问题描述】:

在架构层面上一直在努力解决这个问题。

我有一个可以评论的对象,我们称之为Post。每个帖子都有一个唯一的 ID。

现在我想对该帖子发表评论,我可以使用 ID 作为外键,并且每个 PostComment 都有一个与帖子相关的 ItemID 字段。由于每个帖子都有一个唯一的 ID,因此很容易分配“顶级”cmets。

但是,当我对评论发表评论时,我觉得我现在需要一个 PostCommentComment,它附加到 PostComment 的 ID。由于 ID 是按顺序分配的,因此我不能再简单地使用 ItemID 来区分评论在树中的分配位置。 IE。 Post 和 Post Comment 的 ID 可能都是“5”,因此我的外键关系无效。

这似乎可以无限进行,使用 PostCommentCommentComment 等...

解决这个问题的最佳方法是什么?我是否应该在评论中有一个名为“IsPostComment”的字段或类似的东西来知道要将 ID 附加到哪个集合?这是迄今为止我见过的最好的解决方案,但现在我觉得我需要进行递归数据库调用,这开始变得昂贵。

意思是,我得到一个Post 并得到所有的PostComments where ItemID == Post.ID && where IsPostComment == true

然后我将其作为一个集合,收集PostComments 的所有ID,并再次搜索where ItemID == PostComment[all].ID && where IsPostComment == false,然后无限重复。

这意味着我对每一层都进行了调用,如果我调用 100 个帖子,我可能会进行 1000 次 DB 调用以获取 10 层 cmets。

这样做的正确方法是什么?

【问题讨论】:

  • 请不要crosspost
  • @delnan 在浏览 META 后不确定哪个是发布此内容的正确位置。我将删除另一个帖子,因为这是更有成效的对话。
  • 与 sharepoint 或特别是 sharepoint2010 无关(将这些作为标签,删除...)
  • 它在 SharePoint 中使用并存储在列表中,但我认为这是一个更通用的设计主题,也就是如何在数据库中正确创建树。
  • 如果是这种情况,那么您的最后一句话“如果我调用 100 个帖子,我可能会进行 1000 个 DB 调用”是低估了 :-)

标签: c# sql database-design


【解决方案1】:

我只有一张桌子,名为Post

CREATE TABLE Post
(
    PostID int PK,
    PostContent nvarchar,
    ParentPostID int FK null,
    ...
)

帖子将包含 ID、帖子内容以及您需要的任何其他字段。它还将有一个 ParentPostID,即nullablePostID 的外键。如果ParentPostIDnull,您就知道这是原始帖子。如果有家长,您就知道该帖子是评论。这允许您将 cmets 嵌套到您需要的深度。

【讨论】:

    【解决方案2】:

    我会说你只会有 PostComment,而不是 PostCommentComment 或其他任何东西。

    所有 PostComments 都有一个 PostId,因此当您为该帖子加载 cmets 时,您只需通过 PostId 进行查询。

    所有 cmets 也有 ParentId,它指向另一个注释(顶级 cmets 不会有 ParentId)。这样,每条评论都可以有任意深度的 cmets,但数据在数据库中保持平坦。

    使用给定 PostId 加载所有 cmets 后,您可以使用 ParentId 属性在内存中组装树/层次结构。

    【讨论】:

    • 这几乎正是我的想法(尽管我对数据库设计没有太多经验)。不过,我在想,为什么不同时存储哪个评论线程 ID,以及每个评论的 DepthInThread int 呢?然后,您甚至不必对内存中的 cmets 进行排序,只需将它们直接推送到站点中即可。
    • @RobertChrist 如果该优化适用于您的系统,那当然。有几点需要考虑,如果评论有父、子和孙,它属于哪个线程 ID?它们都属于原始评论吗?知道一个孙子属于一个线程可能不足以避免内存中的排序;您仍然必须解决它应该出现的父级。此外,如果您使用DepthInThread 之类的内容,您应该考虑到如果评论被删除/标记/删除,您可能会在序列中出现空白。
    【解决方案3】:

    将所有 cmets 保持在同一个表结构中,并使用相同的 ID 序列。那么:

    1. 使用COMMENT_DEPTH 字段来指示递归级别。例如,postComment 有COMMENT_DEPTH=0,而postComment 的评论有COMMENT_DEPTH=1

    2. 也使用PARENT_COMMENT 字段。对于具有 COMMENT_DEPTH=0 的 cmets,它应该为 null,如果 COMMENT_DEPTH>0,它应该包含父评论 ID。

    这甚至可以让您拥有多个级别的评论。此外,您可以通过以下方式获取 post cmets:

    WHERE COMMENT_DEPTH=0
    

    您可以通过以下方式对评论 A 进行 cmet:

    WHERE PARENT_COMMENT=A.ID AND COMMENT_DEPTH=A.COMMENT_DEPTH+1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-07
      • 1970-01-01
      • 2018-08-17
      • 2018-08-13
      • 2014-11-18
      • 1970-01-01
      • 1970-01-01
      • 2011-04-15
      相关资源
      最近更新 更多