Вопрос

Я разрабатываю веб-приложение, которое может поддерживать многопоточные комментарии.Мне нужна возможность изменять порядок комментариев в зависимости от количества полученных голосов.(Идентично тому, как работают многопоточные комментарии в Reddit)

Я хотел бы услышать мнения сообщества SO о том, как это сделать.

Как я должен спроектировать Комментарии стол?Вот структура, которую я использую сейчас:

Comment
    id
    parent_post
    parent_comment
    author
    points

Какие изменения следует внести в эту структуру?

Как я должен получить сведения из этой таблицы, чтобы отобразить их правильным образом?(Реализация на любом языке приветствуется.Я просто хочу знать, как сделать это наилучшим образом)

О каких вещах мне нужно позаботиться при реализации этой функции, чтобы снизить нагрузку на процессор / базу данных?

Заранее благодарю.

Это было полезно?

Решение

Хранение деревьев в базе данных - это тема, которая имеет много различных решений.Это зависит от того, хотите ли вы также получить подиерархию (то есть все дочерние элементы элемента X) или вы просто хотите захватить весь набор иерархий и построить дерево O (n) способом в памяти, используя словарь.

Преимущество вашей таблицы в том, что вы можете получить все комментарии к сообщению за один раз, выполнив фильтрацию по родительскому сообщению.Поскольку вы определили родительский элемент комментария учебным / наивным способом, вам нужно построить дерево в памяти (см. Ниже).Если вы хотите получить дерево из базы данных, вам нужен другой способ хранения дерева:Смотрите мое описание подхода, основанного на предварительном вычислении, здесь:http://www.llblgen.com/tinyforum/GotoMessage.aspx ?Идентификатор сообщения=17746 и идентификатор потока= 3208 или с помощью использование сбалансированных деревьев , описанных CELKO здесь:

или еще один подход:http://www.sqlteam.com/article/more-trees-hierarchies-in-sql

Если вы извлекаете все в иерархии в памяти и строите там дерево, это может быть более эффективным из-за того, что запрос довольно прост:выберите ..из комментария, где ParentPost = @id ПОРЯДОК ПО ParentComment ASC

После этого запроса вы строите дерево в памяти, используя всего 1 словарь, который отслеживает кортеж commentId - Комментарий.Теперь вы просматриваете результирующий набор и строите дерево на лету:с каждым комментарием, с которым вы сталкиваетесь, вы можете найти его родительский комментарий в словаре, а затем сохранить комментарий, обрабатываемый в данный момент, также в этом словаре.

Другие советы

Пара вещей, которые также следует учитывать...

1) Когда вы говорите "сортировать как reddit" на основе ранга или даты, вы имеете в виду верхний уровень или все целиком?

2) Когда вы удаляете узел, что происходит с ветвями?Вы перевоспитываете их?В моей реализации, я думаю, что редакторы будут решать - либо скрыть узел и отобразить его как "скрытый комментарий" вместе с видимыми дочерними элементами, скрыть комментарий и его дочерние элементы, либо уничтожить все дерево.Повторное родительское управление должно быть простым (просто установите для родителя ребенка значение "Удаленный родитель"), но все, что связано со всем деревом, кажется сложным для реализации в базе данных.

Я смотрел на литри модуль для 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.Астрономия" без записи для "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" с использованием хранимых процедур, я думаю, вы можете получить лучшее из обоих миров.Вы можете быстро просмотреть дерево комментариев в базе данных, используя свой "path", и при этом обеспечить ссылочную целостность с помощью "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

A некоторые дочерние элементы "3", имеющие идентификаторы "31" и "54", будут:

102.1.3.31
102.1.3.54

Чтобы скрыть узел "3" и его дочерние элементы, вы бы выдали это:

UPDATE comments SET hide=true WHERE path @> '102.1.3';

Хотя я не знаю - это могло бы добавить ненужных накладных расходов.К тому же я не знаю, насколько хорошо поддерживается ltree.

Ваш текущий дизайн в основном подходит для небольших иерархий (менее тысячи элементов).

Если вы хотите выполнить выборку на определенном уровне или глубине, добавьте элемент "level" в свою структуру и вычислите его как часть сохранения

Если производительность вызывает проблемы, используйте приличный кэш

Я бы добавил следующие новые поля в приведенную выше таблицу:

  • thread_id ( идентификатор потока ):идентификатор для всех комментариев, прикрепленных к определенному объекту

  • Дата:дата комментария (позволяет извлекать комментарии по порядку)

  • ранг:ранг комментария (позволяет выбирать порядок комментариев по ранжированию)

Используя эти поля, вы сможете:

  1. извлекать все комментарии в потоке за одну операцию
  2. упорядочивайте комментарии в теме либо по дате, либо по рангу

К сожалению, если вы хотите сохранить свою базу данных запросов близкой к стандарту SQL, вам придется воссоздать дерево в памяти.Некоторые базы данных предлагают специальные запросы для иерархических данных (напримерОракул)

./алекс

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top