我正在开发一个可以支持线程评论的网络应用程序。我需要能够根据收到的票数重新排列评论。(与线程评论的工作方式相同 红迪特)

我很想听听 SO 社区关于如何做到这一点的意见。

我应该如何设计 评论 桌子?这是我现在使用的结构:

Comment
    id
    parent_post
    parent_comment
    author
    points

这个结构应该做哪些改变?

我应该如何从该表中获取详细信息以正确的方式显示它们?(欢迎以任何语言实施。我只是想知道如何以最好的方式做到这一点)

在实现此功能时我需要注意哪些事项,以减少 CPU/数据库的负载?

提前致谢。

有帮助吗?

解决方案

存储在数据库中的树木是具有许多不同的解决方案的受试者。如果你想获取一个子层级以及(所以项目X的所有子女)或它取决于如果你只是想抓住整套层次的,并使用字典中记忆建立的树在O(n)的方式。

您表的优点是你可以在后获取所有的意见在1路走,通过在parentpost过滤。正如你在教科书/天真的方式定义注释的父,你必须建立在内存中的树(见下文)。如果您想获得来自DB的树,你需要用不同的方式来存储一棵树: 见我在这里预先计算基础的方法的描述: http://www.llblgen.com/tinyforum/GotoMessage.aspx?MessageID = 17746&线程ID = 3208 使用平衡树通过CELKO描述此处

或另一种方法中: http://www.sqlteam.com/article/more-trees-hierarchies -in-SQL

如果您在存储层次取一切,并建立树那里,它可以更有效地由于该查询很简单:选择..从哪里注释= ParentPost @id ORDER BY ParentComment ASC

这是查询后,您构建树在内存中只有1字典它记录了元组CommentID的 - 评论。您现在走过的结果集,并建立对飞树:每一个评论,你碰上了,你可以查找它的parentcomment在字典中,然后存储目前还处理了该词典的注释。

其他提示

几件事情也考虑...

1)当你说“有点像reddit的”基于等级或日期,你的意思是顶层或整个事情?

2)当你删除一个节点时,会发生什么情况分支?你重新父母呢?在我的实现,我在想,编辑们决定 - 无论是隐藏节点,并显示为“隐藏注释”与可见孩子一起,隐藏注释和它的孩子,或者核弹整个树。再为人父母应该很容易(只设置chidren的父母被删除的母公司),但任何涉及整个树似乎是棘手的数据库来实现。

我一直在寻找的 ltree 模块PostgreSQL的。它应该包括树的部分快一点的数据库操作。基本上,它可以让你设置一个领域看起来像表:

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”或“顶”的记录。但是,它确实让你做的是这样的东西:

-- 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>

因此线程“102”与“1”的COMMENT_ID的根部评论将具有一个路径:

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保持良好。

您当前的设计基本上适合小型层次结构(少于一千个项目)

如果您想获取特定级别或深度,请将“级别”项添加到您的结构中并将其计算为保存的一部分

如果性能是一个问题,请使用合适的缓存

我将以下新字段添加到上面的表格中:

  • 线程_id:附加到特定对象的所有注释的标识符

  • 日期:评论日期(允许按顺序获取评论)

  • 秩:评论排名(允许按排名获取评论顺序)

使用这些字段您将能够:

  1. 在单个操作中获取线程中的所有评论
  2. 按日期或排名对线程中的评论进行排序

不幸的是,如果您想保留接近 SQL 标准的查询数据库,则必须在内存中重新创建树。一些数据库提供针对分层数据的特殊查询(例如甲骨文)

./亚历克斯

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top