存储树数据的快速关系方法(例如文章的线程注释)

Ste*_*son 15 sql tree database-design data-storage database-agnostic

我有一个cms存储对文章的评论.这些注释可以是线程的,也可以是非线程的.虽然技术上它们是相同的,只是在没有线程的情况下,回复列留空.我的应用程序适用于sqlLite,MySQL和pgsql,所以我需要相当标准的SQL.

我目前有一个评论表

comment_id
article_id
user_id
comment
timestamp
thread (this is the reply column)
Run Code Online (Sandbox Code Playgroud)

我的问题是弄清楚如何最好地代表数据库中的线程注释.也许在一个单独的表中支持没有内容的树集和一个简单的表来保存文本?也许它已经是这样了?或许另一种方式?

如果注释是非线程的,我可以很容易地按时间戳排序.

如果他们是线程我就像这样

ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))
Run Code Online (Sandbox Code Playgroud)

正如您在ORDER BY中看到的那样,注释查询将不会使用索引,因为基于函数的索引实际上只存在于Oracle中.帮我快速点评评论页面.

Aym*_*ieh 19

我真的很喜欢Drupal如何解决这个问题.它为每个评论分配一个线程ID.对于第一条评论,此ID从1开始.如果向此评论添加了回复,则会为其1.1分配ID .对评论的回复1.1给出了线程ID 1.1.1.评论的兄弟1.1给出了线程ID 1.2.你明白了.添加注释时,可以使用一个查询轻松地计算这些线程ID.

呈现线程时,属于该线程的所有注释都在单个查询中获取,并按线程id排序.这为您提供了升序的线程.此外,使用线程ID,您可以找到每个注释的嵌套级别,并相应地缩进.

1
1.1
1.1.1
1.2
1.2.1
Run Code Online (Sandbox Code Playgroud)

有几个问题需要解决:

  • 如果线程id的一个组件增长到2位,则按线程id排序将不会产生预期的顺序.一个简单的解决方案是确保线程id的所有组件都用零填充以具有相同的宽度.
  • 按降序线程ID排序不会产生预期的降序.

Drupal使用名为vancode的编号系统以更复杂的方式解决了第一个问题.至于第二个问题,它是通过在按降序排序时将反斜杠(其ASCII码高于数字)附加到线程ID来解决的.您可以通过检查注释模块的源代码来查找有关此实现的更多详细信息(请参阅函数comment_get_thread之前的大注释).


Tim*_*nen 5

我知道答案有点晚了,但是对于树数据,请使用闭包表 http://www.slideshare.net/billkarwin/models-for-hierarchical-data

它描述了4种方法:

  • 邻接表(简单的父外键)
  • 路径枚举(接受的答案中提到的 Drupal 策略)
  • 嵌套集
  • 闭包表(将祖先/后代事实存储在单独的关系 [表] 中,并带有可能的距离列)

与其他选项相比,最后一个选项具有易于 CRUD 操作的优点。代价是空间,在最坏的情况下,它是数字树节点中的 O(n^2) 大小,但在实践中可能没有那么糟糕。