还要考虑几件事...
1) 当您根据排名或日期说“排序类似于 reddit”时,您是指顶级还是整个事情?
2)当你删除一个节点时,分支会发生什么?你重新养育他们吗?在我的实现中,我认为编辑器将决定——要么隐藏节点并将其与可见的子节点一起显示为“评论隐藏”,要么隐藏评论及其子节点,或者核对整个树。重新养育应该很容易(只需将孩子的父母设置为被删除的父母),但是涉及整个树的任何事情似乎都很难在数据库中实现。
我一直在研究 PostgreSQL 的ltree模块。它应该使涉及部分树的数据库操作更快一些。它基本上可以让您在表中设置一个字段,如下所示:
ltreetest=# select path from test where path <@ 'Top.Science';
path
------------------------------------
Top.Science
Top.Science.Astronomy
Top.Science.Astronomy.Astrophysics
Top.Science.Astronomy.Cosmology
但是,它本身并不能确保任何类型的引用完整性。换句话说,您可以拥有“Top.Science.Astronomy”的记录,而无需“Top.Science”或“Top”的记录。但它确实让你做的是这样的事情:
-- hide the children of Top.Science
UPDATE test SET hide_me=true WHERE path @> 'Top.Science';
或者
-- nuke the cosmology branch
DELETE FROM test WHERE path @> 'Top.Science.Cosmology';
如果结合使用存储过程的传统“comment_id”/“parent_id”方法,我认为您可以两全其美。您可以使用您的“路径”快速遍历数据库中的评论树,并仍然通过“comment_id”/“parent_id”确保引用完整性。我正在设想类似的东西:
CREATE TABLE comments (
comment_id SERIAL PRIMARY KEY,
parent_comment_id int REFERENCES comments(comment_id) ON UPDATE CASCADE ON DELETE CASCADE,
thread_id int NOT NULL REFERENCES threads(thread_id) ON UPDATE CASCADE ON DELETE CASCADE,
path ltree NOT NULL,
comment_body text NOT NULL,
hide boolean not null default false
);
评论的路径字符串看起来像
<thread_id>.<parent_id_#1>.<parent_id_#2>.<parent_id_#3>.<my_comment_id>
因此,comment_id 为“1”的线程“102”的根注释将具有以下路径:
102.1
而comment_id 为“3”的孩子将是:
102.1.3
“3”的一些孩子的 ID 为“31”和“54”将是:
102.1.3.31
102.1.3.54
要隐藏节点“3”及其子节点,您可以发出以下命令:
UPDATE comments SET hide=true WHERE path @> '102.1.3';
我不知道——它可能会增加不必要的开销。另外,我不知道 ltree 的维护情况如何。