Пара вещей, которые нужно учитывать ...
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» или «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>
Таким образом, корневой комментарий потока "102" с комментарием_ид "1" будет иметь путь:
102.1
И ребенок, чей comment_id равен 3, будет:
102.1.3
Некоторые дети из «3» с идентификаторами «31» и «54» будут:
102.1.3.31
102.1.3.54
Чтобы скрыть узел "3" и его дочерние элементы, вы должны выполнить следующее:
UPDATE comments SET hide=true WHERE path @> '102.1.3';
Я не знаю - это может добавить ненужные накладные расходы. Кроме того, я не знаю, насколько ухоженное дерево.