Подтвердить что ты не робот

Как выполнять потоковые комментарии?

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

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

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

Comment
    id
    parent_post
    parent_comment
    author
    points

Какие изменения должны быть внесены в эту структуру?

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

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

Спасибо заранее.

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

Чтобы скрыть node "3" и его детей, вы должны это сделать:

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

Я не знаю, хотя это может добавить ненужные накладные расходы. Плюс я не знаю, насколько хорошо поддерживается литра.

Ответ 3

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

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

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

Ответ 4

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

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

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

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

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

  • получить все комментарии в потоке в одном операторе
  • заказывать комментарии в потоке либо по дате, либо по рангу

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

./Алекс