Реализация рекурсивных комментариев в PHP / MySQL - PullRequest
4 голосов
/ 28 февраля 2010

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

Я предполагаю, что каждый комментарий будет храниться в таблице комментариев и содержать parent_id, который будет внешним ключом для другого комментария. Моя проблема заключается в том, как получить все эти данные без тонны запросов, а затем как эффективно упорядочить комментарии в том порядке, в котором они принадлежат. У кого-нибудь есть идеи о том, как лучше всего это реализовать?

Ответы [ 6 ]

5 голосов
/ 28 февраля 2010

Попробуйте использовать модель с вложенным множеством. Это описано в Управление иерархическими данными в MySQL .

Большим преимуществом является то, что вам не нужно использовать рекурсию для извлечения дочерних узлов, а запросы довольно просты. Недостатком является то, что для вставки и удаления требуется немного больше работы.

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

1 голос
/ 29 марта 2012

Мне тоже пришлось реализовать рекурсивные комментарии. Я сломал голову вложенной моделью, позвольте мне объяснить, почему:

Допустим, вы хотите комментарии к статье. Давайте назовем корневые комментарии комментариями, непосредственно прикрепленными к этой статье. Давайте звоним, отвечаем, комментируем комментарии, которые являются ответом на другой комментарий.

Я заметил (к сожалению), что хочу, чтобы корневые комментарии были упорядочены по дате, НО я хотел, чтобы ответные комментарии были заказаны, дата asc !! Парадоксал !!

Таким образом, вложенная модель не помогла мне уменьшить количество запросов.

Вот мое решение:

Создать таблицу комментариев со следующими полями:

ID
article_id
parent_id (обнуляемый)
date_creation
электронная почта
whateverYouLike
последовательность
глубина

3 ключевых поля этой реализации: parent_id, sequence и глубина. parent_id и глубина помогают вставлять новые узлы.

Последовательность - это поле реального ключа, это своего рода эмуляция вложенной модели.

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

Самый последний корневой комментарий должен быть с наибольшим порядковым номером.

Теперь ответьте на комментарии: у нас есть два случая: ответить для корневого комментария или ответить для ответного комментария.

В обоих случаях алгоритм одинаков: возьмите последовательность родителей и найдите ее, чтобы получить ваш порядковый номер. Затем вы должны обновить номера последовательностей, которые находятся ниже родительской последовательности и выше базовой последовательности, это последовательность корневого комментария чуть ниже соответствующего корневого комментария.

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

1 голос
/ 23 марта 2012

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

Поле последовательности будет служить для упорядочения комментариев. И поле глубины будет указывать уровень рекурсии комментария.

Тогда сложная часть будет делать правильные обновления, когда пользователи вставляют новые комментарии.

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

1 голос
/ 09 марта 2012

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

Вот ссылки:

http://www.evanpetersen.com/index.php/item/php-and-mysql-recursion.html

и

http://www.evanpetersen.com/index.php/item/php-mysql-revisited.html

1 голос
/ 01 марта 2010

Я обычно работаю с родительско-дочерней системой.

Например, рассмотрим следующее:

Комментарий к таблице ( CommentID, PageId, Идентификатор пользователя, комментарий [, parentID] )

parentID - это внешний ключ для commentID (из той же таблицы), который является необязательным (может быть NULL).

Для выбора комментариев используйте это для корневого комментария:

SELECT * FROM comments WHERE pageID=:pageid AND parentID IS NULL

А это для ребенка:

SELECT * FROM comments WHERE pageID=:pageid AND parentID=:parentid
1 голос
/ 28 февраля 2010

Вот другой сайт , предоставляющий информацию об этом методе + некоторый исходный код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...