[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Подскажите схему каталога
paul85
Добрый день, уважаемые форумчане!

Работаю над задачей хранения каталога произвольной вложенности. По сути получается дерево. Существуют различные схемы хранения деревьев в БД (Adjacency List, Path Enumeration, Nested Sets и Closure Table).

Соответственно, при выводе информации на экран, нужно запрашивать непосредственных потомков текущего элемента и всех предков (для bread crumbs).

Какую схему вы бы посоветовали выбрать? В случае AL легко брать потомков, но целая проблема с предками. PE проблема и в том и в другом. Потому, что для bread crumbs помимо пути, нужны еще и названия нод. NS вообще сплошной геморрой... Тем более, как мне кажется, NS наиболее всего подходит, когда требуется выбирать целиком ветвь, которой принадлежит узел.

Получается правильнее всего реализовать с помощью CT? Или, вероятно, использовать какие-то миксы, скажем, AL+PE? Как грамотнее всего решить задачу? Думаю с ней практически все сталкивались...

Спасибо!
chee
paul85, обычно решается задача комбинированием двух подходов. Я например когда-то решал с помощью Adjacency List и Materialized Path.

Кстати гуглится вероятная проблему, которую решили на хабре http://habrahabr.ru/post/226741/

_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
Michael
В старой своей самописной цмс использовал nested sets. Не самая легкая для реализации, произвольное перемещение я так и не стал делать, и как по мне не сильно вся эта математическая круть и нужна. Хотя если прям какие то навороченные деревья, в которых редко надо операции изменения делать то нормалек.

Сейчас, в той цмс что пишу на yii2, остановился на Materialized Path, интуитивное дерево, легкое в реализации. Недостатки считаю несущественными.
Например что выше было сказано:
1) хлебные крохи - это элемент который обычно единоразово выводится на странице, так что 2 запроса не жалко.
2) Не вижу проблем с непосредственными потомками вообще. На равенство проверяется путь и все.

_____________
There never was a struggle in the soul of a good man that was not hard
vagrand
Я не знаю как называется этот подход, но я всегда делаю по такому алгоритму:
1. Первая таблица для хранения всех итемов дерева в виде плоского списка. Каждому итему сохраняем только ID его непосредственного родителя.

2. Вторая таблица в которой для каждого итема сохраняем ID всех кто выше него. Т.е. связь для итема будет 1:M.

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

_____________
Senior PHP developer: PHP5, MySQL, JavaScript, CakePHP, Yii/Yii2, Zend Framework, Smarty, XML/Xslt, JQuery, Jquery Mobile, Bootstrap, ExtJS, HTML, HTML5, CSS, Linux, SVN, Git, Memcached, Redis, MongoDB, Zend Guard, Ioncube, FFMpeg, PayPal, Webmoney, Qiwi, Facebook API, Vkontakte Api, Google API, Twitter Api, Steam Api.
Junior Android Developer: Android SDK, многопоточность, работа с HTTP запросами, JSON, SQLite, фрагменты.
paul85
Цитата (Michael @ 15.11.2014 - 10:18)
Не вижу проблем с непосредственными потомками вообще. На равенство проверяется путь и все.

Michael, а как проверять-то? Ведь по правилам путь указывается вместе с текущей нодой. То есть нужно что-то типа регулярного выражения в запросе? Или имеется ввиду усеченная модель, где в пути не учитывается текущая нода?

Тут я вот в чем вижу довольно большую проблему. Если понадобится переместить sub-tree в другую ветвь, то пересчитывать/переписывать пути потомков трудоемко.

Цитата (vagrand @ 15.11.2014 - 12:30)
Я не знаю как называется этот подход, но я всегда делаю по такому алгоритму:

Интересный подход! Сочетает в себе Adjacency List и элементы Closure Table. А как считать всех вышестоящих родителей для новой ноды? С помощью запроса в цикле? Мы же не знаем вложенность заранее, то есть применить JOIN не представляется возможным. Или я чего-то не понимаю?

Таскать sub-tree более или менее понятно как. Но опять-таки пересчитывать пути для каждого потомка (в составе sub-tree). Хотя в данном варианте это делать, мне кажется, попроще. С логической точки зрения. Понятнее.

Свернутый текст
Частенько бывает, звонит заказчик и говорит, мол, ошиблись - перенеси. И тут, вспомнив это, я понял что nested sets не годится. biggrin.gif
vagrand
paul85
Цитата
. А как считать всех вышестоящих родителей для новой ноды?


Выборка всех родителей происходит из второй таблицы. Указываем id текущего итема и получаем ID всех родителей.

Что же касается перемезения, то тут тоже все довольно просто. Удаляем текущие связи итема с родителями. Берем ID нового непосредственного родителя итема и для него вытаскиваем всех его родитиелей. Ну а потом сохраняем этот списко для перемещенного итема.

_____________
Senior PHP developer: PHP5, MySQL, JavaScript, CakePHP, Yii/Yii2, Zend Framework, Smarty, XML/Xslt, JQuery, Jquery Mobile, Bootstrap, ExtJS, HTML, HTML5, CSS, Linux, SVN, Git, Memcached, Redis, MongoDB, Zend Guard, Ioncube, FFMpeg, PayPal, Webmoney, Qiwi, Facebook API, Vkontakte Api, Google API, Twitter Api, Steam Api.
Junior Android Developer: Android SDK, многопоточность, работа с HTTP запросами, JSON, SQLite, фрагменты.
Michael
paul85, я в пути не использую id текущей ноды.

_____________
There never was a struggle in the soul of a good man that was not hard
paul85
В итоге остановился на Closure Table + Adjacency List. Примерно то самое, о чем говорил vagrand.

Если кому интересно, Adjacency List решил включить для отрисовки деревьев. Closure Table не предоставляет такой возможности, к сожалению. Вангую, что клиент рано или поздно захочет видеть свой каталог в виде дерева (в админке). Ну и плюс ко всему необходимо таскать subtrees, что в случае с Materialized Path гораздо проблематичнее. Про Nested Sets вообще промолчу...

Всем откликнувшимся спасибо!
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.