Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Коментарии и постраничка, какой алгоритм лучше


Автор: Sanchezzz 9.7.2012, 11:27
Добрый день какой алгоритм лучше использовать учитывая вложенность комментариев для разбиение на постраничку учитывая что вывод иерархии дерева
тесть потомки должны выводится.
...
comment_id        bigint(18)    //родитель                
comment_pid        bigint(18)    // потомок
comment_left       bigint(18)    // для nested 
comment_right     bigint(18)    // для nested 
comment_level     int(11)        //уровень для nested
user_id                bigint(18)    // ид узера
comment_text      text            // текст
...

из двух доступных способах есть: родитель и предок  или nested sets.

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



Автор: Fortop 9.7.2012, 18:59
Цитата(Sanchezzz @  9.7.2012,  11:27 Найти цитируемый пост)
Добрый день какой алгоритм лучше использовать учитывая вложенность комментариев для разбиение на постраничку учитывая что вывод иерархии дерева

Без шансов.
Т.е. сделать можно, но лишь если ограничить уровень вложенности для которого работает пагинация.
Или городить сложный огород с подсчетом потомков, но и это не гарантирует что вам не попадется ветка на 1000 комментариев.

Выводите лентой или подгружайте потомков по доп-клику.

А как хранить - в Nested Sets или Adjacency List (AL) зависит далеко не от требований вывода.

Автор: Sanchezzz 9.7.2012, 20:30
Цитата

Выводите лентой или подгружайте потомков по доп-клику

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

Автор: Fortop 9.7.2012, 20:57
Цитата(Sanchezzz @  9.7.2012,  20:30 Найти цитируемый пост)
Цитата(Fortop @  9.7.2012,  18:59 Найти цитируемый пост)
 или подгружайте потомков по доп-клику.

это не вариант запарит пользователей 

Цитата(Sanchezzz @  9.7.2012,  20:30 Найти цитируемый пост)
Захочет почитать что дальше нажмет на кнопку подгрузить еще.

Я это...
А разница в чем?
Моя не понимай.

Цитата(Sanchezzz @  9.7.2012,  20:30 Найти цитируемый пост)
Захочет почитать что дальше нажмет на кнопку подгрузить еще.

Если не критично что ветка треда будет разрываться страницами, то можно делать.

P.S. можно посмотреть на вконтакт, как там сделана автоподгрузка.


Автор: Sanchezzz 9.7.2012, 22:41
в чем критичность загрузке дополнительных элементов по клику(плюсику) в том что это запарит пользователя кликать на каждый узел дерева просто  опыт был такой с погрузкой дерева людям не нравилось им не удобно было

Цитата

Цитата

Цитата(Sanchezzz @  9.7.2012,  20:30 )
Захочет почитать что дальше нажмет на кнопку подгрузить еще.

Если не критично что ветка треда будет разрываться страницами, то можно делать.

а тут есть подводный камень об который придется споткнутся так как сортировка идет вывода по дате добавления а данные выводится в виде дерева то в некоторых узлах можно недосчитаться комментариев в случаи если использовать метод: родитель=потомок. Если комментируемы люди комментируют старые записи.
Естественно выборка идет 1 запросом, рекурсией проверять не выгодно.

Есть одна мысль, выбрать только родителей с параметром SQL_CALC_FOUND_ROWS что бы сразу считать и брать основные элементы как за количество записей и разбивать на страницы
Затем выбрать все комментарии у кого больше парент или level больше 0 и подставить в выбраные 100-1000 элементов  дополнительные вложенные.
Обычно комментируют друг друга не так уж и много дискуссия идет 3-10+ вложенных во вложенные в родитель.

Раз речь пошла о ВК
Авто подгрузка не удобна тем что ты не знаешь когда конец, это не удобство которое руководство вк придумало подумав что удобно.
У меня на странице в день в контакте новостей приходит очень много  я все не успеваю просматривать все.
Загрузил колбасу  нажал случайно переход по ссылки вернулся и приходится грузить все заново. 
Еще одна фича которая меня там раздражает кнопка вверх слева по которой я постоянно попадаю раздражает, приходится напрягать мозг и держать курсор всегда в правой части экрана ( на хабр и то лучше сделали стрелку вверх ура хабру)

«нельзя заставлять пользователя думать» — первый и главный принцип построения популярных систем.


Автор: Fortop 12.7.2012, 13:56
Цитата(Sanchezzz @  9.7.2012,  22:41 Найти цитируемый пост)
в чем критичность загрузке дополнительных элементов по клику(плюсику) 

Не доводите идею до абсурда.

Открывайте ветку сразу или на определенную глубину 2-3-4 уровня (или всю целиком, если длинные ветки нетипичны)
Или же на определенное число сообщений.


Цитата(Sanchezzz @  9.7.2012,  22:41 Найти цитируемый пост)
а тут есть подводный камень об который придется споткнутся так как сортировка идет вывода по дате добавления а данные выводится в виде дерева то в некоторых узлах можно недосчитаться комментариев в случаи если использовать метод: родитель=потомок. Если комментируемы люди комментируют старые записи.
Естественно выборка идет 1 запросом, рекурсией проверять не выгодно.

Вообще не понял.
Как вы можете чего-то не досчитаться?

Цитата(Sanchezzz @  9.7.2012,  22:41 Найти цитируемый пост)
Авто подгрузка не удобна тем что ты не знаешь когда конец

В комментариях там есть автоподгрузка и виджет пагинации.
Заходишь на последнюю страницу и вперед.

Цитата(Sanchezzz @  9.7.2012,  22:41 Найти цитируемый пост)
«нельзя заставлять пользователя думать» — первый и главный принцип построения популярных систем.

Вообще-то это первый и главный принцип выращивания быдла.
Юзабилити же выражается несколько в другом.

Автор: Sanchezzz 12.7.2012, 22:27
Цитата

Вообще не понял.
Как вы можете чего-то не досчитаться?

Классический способ постройки древа

если дерево строится путем выборки 1 запросом в котором применяем лимит 0,10 
Затем составляем массив для рекурсии 
Код

foreach($arrComents as $item):
    $treeComents[$item['comment_pid']][] = $item;
endforeach;

Затем делаем вывод опять дедушкиным способом.
Цитата

function tree ( $parent, $tree){
print "<ul>";
 if(!isset($tree[$parent]))    return;
foreach($tree[$parent] as $item){
 print "<li>{$item["comment_text"]}";
  tree ($item["comment_id"], $tree );
 print "</li>";
}
print "</ul>";
}


то получаем неполное дерево  так как новые комментарии могут быть в подвертке ранее добавленных комментариев
выбирать циклом из базы 2 уровень ,3 уровень итд просоnj не выгодно колхозно.


Автор: Fortop 13.7.2012, 00:44
Цитата(Sanchezzz @  12.7.2012,  22:27 Найти цитируемый пост)
Классический способ постройки древа

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

Цитата(Sanchezzz @  12.7.2012,  22:27 Найти цитируемый пост)
то получаем неполное дерево

Да с чего оно вдруг неполное?
Что у вас что-то добавилось в ветках, которые вы вывели ранее?
Так это не ваши половые трудности. Оно у вас в любом случае будет добавляться, а вы будете иметь лишь определенный снапшот/серию снапшотов.
Или же вам надо ставить комет и в реальном времени пушить изменения клиенту.

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

Автор: Sanchezzz 14.7.2012, 12:19
Классический способ постройки древа
Цитата

Я не знаю такого.

А какой вы знаете способ постройки древа 1 запросом ?

Цитата

Да с чего оно вдруг неполное?
 Сделай дерево иерархии id , parent 1 запросом и примени разбивку на страницы причем страницы разбиваются по тем элементам которые имеют потомка 0 все подветки комментов должны выводится.
Приведенный способ выше постом годится для полного вывода дерева для постраничного не годится.

Цитата

Что у вас что-то добавилось в ветках, которые вы вывели ранее?
Так это не ваши половые трудности. Оно у вас в любом случае будет добавляться, а вы будете иметь лишь определенный снапшот/серию снапшотов.

Наверное всетоки мои проблемы мне это нужно показать пользователю а не для себя хранить)


Что бы поставить крест привожу пример как выгладить должно.

На странице 1 мы хотим вывести например по 10 комментариев на страницу
 
Код

== Страница 1  ==
Комент 1 потомок 0 , Дата: сегодня 12:00
Комент 2 потомок 0 , Дата: сегодня 12:01
Комент 3 потомок 0 , Дата: сегодня 12:06
    Комент 5 потомок 3 , Дата: сегодня 12:10
    Комент 6 потомок 3 , Дата: сегодня 12:17
        Комент 8 потомок 6 , Дата: сегодня 16:00
                Комент 19 потомок 6 , Дата: сегодня 19:00
    Комент 7 потомок 3 , Дата: сегодня 14:55
    Комент 9 потомок 3 , Дата: сегодня 16:01
Комент 4 потомок 0 , Дата: сегодня 12:08
Комент 10 потомок 0 , Дата: сегодня 16:03
Комент 11 потомок 0 , Дата: сегодня 16:09
Комент 12 потомок 0 , Дата: сегодня 16:09
Комент 13 потомок 0 , Дата: сегодня 16:09
Комент 14 потомок 0 , Дата: сегодня 16:09
Комент 15 потомок 0 , Дата: сегодня 16:09

<a> еще 10 комментариев </a>

 == Страница 2  ==
Комент 16 потомок 0 , Дата: сегодня 18:00
Комент 17 потомок 0 , Дата: сегодня 18:40
Комент 18 потомок 0 , Дата: сегодня 18:41
...
<a> еще 10 комментариев </a>



Выход построения на постранички дерева сохраняя структуру вывода я нашел  4:

1 Nested Sets.  не стал с ним играется отпугнуло постоянного перестроение ветки дерева при добавлении , это вариант отпал сразу я посчитал это не эффективно так как сам процесс комментирования очень частый нежели публикация страниц  и придется перестраивать ветку дерево постоянно + получаем геморой с выборками судя по отзывам) .
А так для хранения вполне пригодная конструкции для каталога где не так редко добавляется информация.

2(Этот способ мне подчти понравился но нашел его как облегчить) Привожу суть мысли как могу)
Выбрать родителей и на их основе разбить постранично элементы на страницы (например по 100 комментов на страницу )  то что отображаем берем все ID комментов  и делаем дополнительный под запрос по paretn_id in (ID) получаем все ID ,   далее повторяем эту процедуру до тех пор пока не получим результат 0. 
Этот способ тоже не понравился потому что рекурсивно делаем запросы в глубь

3 Сделать 1 запрос с множеством RIGHT JOIN на количество возможных уровней, если я не ошибаюсь  в mysql есть ограничения на количество подключаемых таблиц
Способ тоже не понравился .  После этого способа я вернулся ко 2 способу стал думать как облегчить конструкцию...

4 Фактически это способ номер 2 оптимизированный. Сделал в таблице дополнительное поля rootid. Если вкратце суть такова: 
Первый запрос получает нужные нам количество комментариев 100 штук с парентом 0. 
Второй запрос получает все комментария по rootid  дополнительных.  Where rootid in ( 100 id ... ) которые потом складываем в общий массив. Через рекурсию обрабатываем массив и вложенности строим дерево.

Также придется учесть один момент для подветок добавления комментариев нужно всегда будет находить id родителя для rootid
2 способа один из них невменяемый=))) 
1 невменяемый: пробегается рекурсией до pareте_id=0 так мы получим id родителя комментариев для rootid
2 вменяемый:     так как коммент добавляем выставляется по pareте_id  и idшника родителя спросим у этого pareте_id какой у него rootid если pareте_id=0 то отдаем ему id как родителя.
Минус в этом подходе если будут перемещатся узлы дерева между веткой придется как и с Nested Sets перестраивать всю ветку меняя rootid но этого не будет это же комментарии а не какие-либо категории.
Если кто увидит минус в 4способе и проблемы судовольствием прочитаю ваше мнение.

Вывести целиком дерево 5000 комментариев нет не каких проблем но надо-ли отдавать пользователю пару 3-10мб текста, да и такое количество комментов редкость.


Автор: Fortop 16.7.2012, 11:53
Цитата(Sanchezzz @  14.7.2012,  12:19 Найти цитируемый пост)
А какой вы знаете способ постройки древа 1 запросом ?

Дерево не строится запросами. Вообще. Ни одним ни двумя.

Хотя вру. Для некоторых БД, отличных от MySQL, есть варианты работы с xml

Цитата(Sanchezzz @  14.7.2012,  12:19 Найти цитируемый пост)
Наверное всетоки мои проблемы мне это нужно показать пользователю а не для себя хранить)

Вам нужно не показать это пользователю, а чтобы пользователю было удобно.
Вы не можете сделать удобную пагинацию при древовидном стиле не ограничившись уровнем.
О чем я уже говорил
Цитата(Fortop @  9.7.2012,  18:59 Найти цитируемый пост)
Т.е. сделать можно, но лишь если ограничить уровень вложенности для которого работает пагинация.


Добавлено через 47 секунд
Sanchezzz, а вообще поставить disqus и не парить себе мозг

Автор: Sanchezzz 16.7.2012, 21:28
disqus не подходит под наши задачи по многим пунктам. 
Дизайн, другая система пользователей, также у нас уже закончена большая часть м по текущему вопросу. к тому же  многие фишки этого сервера уже реализованы.

Цитата

Дерево не строится запросами. Вообще. Ни одним ни двумя.
 Тогда сколькими? Если все получилось задуманное в 1-2 запроса.
Цитата

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

Конечно у меня есть уровень вложенности максимальный  он 0-3 все остальные уровни игнорируются и выводятся как 3 уровень. 
Есть возможность сделать контроль чтобы контролировать уровень вложенности при добавление но это я не вижу смысла.
Я не псих все дерево выводить в ul li ul li у меня другой подход , каждый уровень имеет свой уровень margin-left отступа все элементы выше 3 уровня находятся на одном уровне вложенности с 3.

Постраничка 2 вида: 
1) это обычная пагинация с погрузкой влево право(карусель) со списком страниц.
2) вертикальная  подзагрузка кнопкой "ёще" и счетчиком сколько комментов осталось.

Так о каких неудобствах идет речь, когда  есть руки голова и инструмент?




Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)