Выбор категорий для контента на сайте

sanu0074

Новичок
Я делаю редактор контента в админке (самопальная кмс), столкнулся с потребностью выбирать категории для элементов. Сделал несколько таких видов, можно дать элементу несколько категорий, также категорией элемента в таком случае может быть какое-то свойство других элементов, например элементу из группы "шары" мы можем дать категорию-свойство - цвет - группы элементов "карандаши". Но, есть еще один случай, когда дерево админ может сам выстроить, и получится что у каждого элемента в этом дереве будут свойства: id,name,group,parent_id. Проблема заключается в том, что при добавлении такого поля к элементу контента (у него свойство group такое-же как и в дереве категорий), появляется список выбора таких категорий (<select>), при выборе (onchange) посылаем запрос на сервер с ID выбранной категории, чтобы проверить есть ли в дереве категорий строка у которой parent_id равен присланному ID и с таким group. Если есть выгружаются данные найденных категорий и строится рядом еще один <select> с ними. Здесь плохо то что нужно слать много запросов при выборе туда-сюда этих категорий. Я вообще подозреваю что леплю какой-то ужасный велик! Я бы хотел чтобы это дерево выгружалось сразу полностью, и можно было без всяких запросов делать выбор между категориями и под-категориями. Как это сделать? Дайте дельный совет пожалуйста.
 

AnrDaemon

Продвинутый новичок
СРАЗУ ВСЁ - это грубо и неэффективно. (У меня сейчас как раз CMS так работает - примерно 600 категорий грузится из БД каждый раз, когда надо поменять меню - ЭТОВЦ! Даже с учётом кеширования, проблема перерастает в проблему инвалидации кеша, и дальше до бесконечности.)
А вот подгружать один-два следующих уровня, и пока пользователь думает над выбором, асинхронно грузить остальное - возможно.
Я бы даже сделал так: дал пользователю (обычно короткий) список верхних категорий, а по выбору грузил два следующих уровня подкатегорий. И, естественно, хранил бы уже загруженные списки в странице пока пользователь не наиграется.
По крайней мере я сейчас делаю нечто аналогичное на стороне сервера - выворачиваю объект "категория" "мехом внутрь", чтобы не SQL снаружи напихивал категории данными, а категория сама подтягивала чилды при необходимости (99,(9)% времени такой необходимости просто нет).
Естественно, это всё работает легко только при отсутствии циклических ссылок.
 

Активист

Активист
Команда форума
Я делаю редактор контента в админке (самопальная кмс), столкнулся с потребностью выбирать категории для элементов. Сделал несколько таких видов, можно дать элементу несколько категорий, также категорией элемента в таком случае может быть какое-то свойство других элементов, например элементу из группы "шары" мы можем дать категорию-свойство - цвет - группы элементов "карандаши". Но, есть еще один случай, когда дерево админ может сам выстроить, и получится что у каждого элемента в этом дереве будут свойства: id,name,group,parent_id. Проблема заключается в том, что при добавлении такого поля к элементу контента (у него свойство group такое-же как и в дереве категорий), появляется список выбора таких категорий (<select>), при выборе (onchange) посылаем запрос на сервер с ID выбранной категории, чтобы проверить есть ли в дереве категорий строка у которой parent_id равен присланному ID и с таким group. Если есть выгружаются данные найденных категорий и строится рядом еще один <select> с ними. Здесь плохо то что нужно слать много запросов при выборе туда-сюда этих категорий. Я вообще подозреваю что леплю какой-то ужасный велик! Я бы хотел чтобы это дерево выгружалось сразу полностью, и можно было без всяких запросов делать выбор между категориями и под-категориями. Как это сделать? Дайте дельный совет пожалуйста.
Если категорий много (большое дерево) - не проще ли заюзать autocomplete, который предлагает пользователю группу (если их десятки тысяч - то ускорить можно через Sphinx Search)? А про свойства, я вообще не понял как они с группами завязаны и почему. Группы контента, это группы, а свойства контента (например - цвет - белый) - это свойства, свойства хранятся отдельно в таблице "характеристик (characteristics)" вида [group_id, product_id, attribute_id, value_id] - причем уникальный составной индекс (unique primary key) делается на эти поля в той же очередности, используя такую таблицу вы можете легко выгрузить любую вариацию данных. В отдельной таблице вы храните справочники [attribute_id, attibute_name] и [value_id, value_name] и джойните их после выборки из таблицы "характеристик". Когда вы привязываете конкретное свойство (характеристику), например цвет к группе "карандаши", то у вас возникает проблема, что вы привязаны к этой группе, а если вы даете возможность на любой контент повесить неограниченные и не привязанные к группе характеристики (цвет), то сможете его указать как для группы "шары" , так и для группы "карандаши". Если вам понадобится вывести только красные шары, то вы делаете SQL запрос вида "select * from characteristics where `group_id` = '1' && `attribute_id` = '2' && `value_id` = '3' ", где 1 - группа "шары", 2 - свойство "цвет", 3 - значение "красные". Если вам нужно выгрузить все имеющие свойства группы (или групп, в т.ч. всего дерева), то опять же простой SQL - select * from characteristics where `group_id` in ('1', '2','3') group by `attribute_id`; Кроме того, подобную структуру БД поддерживает и Sphinx Search, называется Multi-valued attribute (MVA), что очень удобно при организации полнотекстового поиска с параметрами (атрибутами) по огромным базам данных. Главное - обеспечте уникальность текстового значения как для наименования атрибутов, так и для справочника значений. В случае много-миллионых текстовых интерпретаций того или иного текстового значения атрибутов - то разумнее будет добавить в MySQL по мимо индекса на строку - индекс - число crc32 - от текстового значения и проверять существование значения параметра запросом вида "select value_id where `crc32` = crc32('красный') && `value_name` = 'красный'". Используя ключ-значение crc32 от строки - можно и легко систематезировать мемкеш, да и crc32 в два раза быстрее md5. Для особых ценителей производительности при вычислении хешей есть xxHash
 
Последнее редактирование:

Absinthe

жожо
СРАЗУ ВСЁ - это грубо и неэффективно. (У меня сейчас как раз CMS так работает - примерно 600 категорий грузится из БД каждый раз, когда надо поменять меню - ЭТОВЦ! Даже с учётом кеширования, проблема перерастает в проблему инвалидации кеша, и дальше до бесконечности.)
Стоит убрать из таблицы категорий многомегабайтные блобы.

P.S. Дерево строится в 1 проход по данным.
 
Сверху