Я пытаюсь написать систему комментариев, где люди могут комментировать другие комментарии, и они отображаются в виде рекурсивных потоков на странице. ( Система комментариев Reddit – пример того, чего я пытаюсь достичь), однако я смущен тем, как реализовать такую систему, которая не будет очень медленной и дорогостоящей вычислительной.
Я предполагаю, что каждый комментарий будет храниться в таблице комментариев и содержать parent_id, который будет внешним ключом для другого комментария. Моя проблема заключается в том, как получить все эти данные без тонны запросов, а затем, как эффективно организовать комментарии в этом порядке. Кто-нибудь есть идеи о том, как наилучшим образом реализовать это?
Попробуйте использовать вложенную модель набора. Он описан в разделе «Управление иерархическими данными в MySQL» .
Большим преимуществом является то, что вам не нужно использовать рекурсию для извлечения дочерних узлов, а запросы довольно просты. Недостатком является то, что вставка и удаление требует немного больше работы.
Он также очень хорошо масштабируется. Я знаю одну чрезвычайно огромную систему, в которой хранятся иерархии обсуждений с использованием этого метода.
Вот еще один сайт, содержащий информацию об этом методе + некоторый исходный код.
Это просто предложение, но, поскольку я столкнулся с той же проблемой прямо сейчас, как насчет добавления поля последовательности (int) и поля глубины в таблице комментариев и обновлять его по мере добавления новых комментариев.
Поле последовательности будет служить для упорядочивания комментариев. Поле глубины указывает на уровень рекурсии комментария.
Тогда жесткая часть будет делать правильные обновления, поскольку пользователи вставляют новые комментарии.
Я еще не знаю, как сложно это реализовать, но я уверен, что когда-то был реализован, у нас будет увеличение производительности по сравнению с вложенными решениями на основе моделей.
Я создал небольшой учебник, объясняющий основные концепции рекурсивного подхода. Как говорили выше люди, рекурсивная функция также не масштабируется, однако вставки намного эффективнее.
Вот ссылки:
http://www.evanpetersen.com/index.php/item/php-and-mysql-recursion.html
а также
http://www.evanpetersen.com/index.php/item/php-mysql-revisited.html
Я нормально работаю с родительско-детской системой.
Например, рассмотрим следующее:
Комментарий таблицы (commentID, pageID, userID, comment [, parentID])
parentID является внешним ключом для commentID (из той же таблицы), который является необязательным (может быть NULL).
Для выбора комментариев используйте это для комментария «root»:
SELECT * FROM comments WHERE pageID=:pageid AND parentID IS NULL
И это для ребенка:
SELECT * FROM comments WHERE pageID=:pageid AND parentID=:parentid
Мне также пришлось реализовать рекурсивные комментарии. Я сломал голову с вложенной моделью, позвольте мне объяснить, почему:
Допустим, вам нужны комментарии к статье. Давайте назовем корневые комментарии комментариями, непосредственно связанными с этой статьей. Давайте позвоним ответам на комментарии, которые являются ответом на другой комментарий.
Я заметил (к сожалению), что я хотел, чтобы корневые комментарии заказывались по дате desc, НО я хотел, чтобы комментарии к ответам были заказаны с датой по возрастанию !! Парадоксально !!
Таким образом, вложенная модель не помогла мне уменьшить количество запросов.
Вот мое решение:
Создайте таблицу комментариев со следующими полями:
Я бы
article_id
parent_id (nullable)
date_creation
Эл. адрес
как хочешь
последовательность
глубина
3 ключевыми полями этой реализации являются parent_id, последовательность и глубина. parent_id и depth помогают вставлять новые узлы.
Последовательность – это реальное ключевое поле, это своего рода эмуляция вложенной модели.
Каждый раз, когда вы вставляете новый корневой комментарий, он кратен x. Я выбираю x = 1000, что в основном означает, что у меня может быть 1000 максимальных вложенных комментариев (это единственный недостаток, который я нашел для этой системы, но этот предел можно легко изменить, этого достаточно для моих нужд сейчас).
Самый последний корневой комментарий должен быть самым большим порядковым номером.
Теперь ответьте на комментарии: у нас есть два случая: ответ для комментария root или ответ для ответа.
В обоих случаях алгоритм один и тот же: возьмите последовательность родителя и получите один, чтобы получить порядковый номер. Затем вам нужно обновить номера последовательностей, которые находятся ниже последовательности родителя и выше базовой последовательности, которая представляет собой последовательность комментариев root чуть ниже соответствующего комментария к корню.
Я не ожидаю, что вы все это поймете, потому что я не очень хороший объяснитель, но надеюсь, что это может дать вам новые идеи. (По крайней мере, это работало для меня лучше, чем вложенная модель: = меньше запросов, что является реальной целью).