MySQL: как правильнее организовать поиск по каталожному дереву?

Asar
На сайте с 23.08.2004
Offline
320
555

Обычное многоуровневое дерево:

Категория (уровень 1)

ПодКатегория (уровень 2)

ПодПодКатегория (уровень 3)

ПодПодПодКатегория (уровень 4)

Объект.

Усложнение 1:

Один и тот же объект может принадлежать разным категориям, а у одной и той же категории может быть несколько разных названий.

Усложнение 2:

Количество уровней может быть разным, и 4 — это не предел.

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

Навскидку: лепим в таблице Объектов поле Категории и запихиваем туда все родительские категории через какой-нибудь там прямой слэш. Получаем что-то вроде |Категория 1|Категория 2|Категория 3 и т.д.

Плюсы: нам по барабану взаимотношения между категориям, всегда найдем объект по любой из них (т.е. убираем оба усложнения).

Минусы: искать придется через LIKE %%, соответственно, индекс не сработает, и все будет медленно.

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

Может кто-нибудь подсказать решение?

CP
На сайте с 12.08.2009
Offline
101
#1

А чем таблица связей не подходит Many to Many ? Гибко и быстро будет. Если данных не сильно много.

Через слеш - тоже можно, но like будет неплохо ресурсов потреблять. Да и будут проблемы, когда название категории надо будет изменить. Придется вам всю таблицу чекать и изменять.

Профессиональный frontend: JS, html,css, Single-Page App (/ru/forum/964386)
Asar
На сайте с 23.08.2004
Offline
320
#2

Вот и я уж грешным делом подумал, что это ближе не к категориям даже, а каким-нибудь там статейным тегам получается, и многое ко многим сюда можно лепить. Несколько пугает только то, что эти многие исчисляются миллионами...

---------- Добавлено 22.05.2016 в 19:13 ----------

Или попробовать заморочиться FULLTEXT'ом...

totamon
На сайте с 12.05.2007
Offline
437
#3
Asar:
а у одной и той же категории может быть несколько разных названий.

это треш какой-то, и как вы категории храните и эти разные названия?

надеюсь категории в отдельной таблице, не знаю про множественные, а так задача банальная, таблица многие ко многим через ид, в объекте можно избыточно хранить список категорий, только в виде ид через запятую, по нему можно выбирать категории через IN ("1,3,7")

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

юзер может и по названию ищет, но скрипт в БД искать должен по ИД, для этого задать связи и индексы

Домены и хостинг https://8fn.ru/regru | Дедик от 3000р https://8fn.ru/73 | VPS в Москве https://8fn.ru/72 | Лучшие ВПС, ТП огонь, все страны! https://8fn.ru/inferno | ХОСТИНГ №1 РОССИИ https://8fn.ru/beget
C
На сайте с 20.04.2015
Offline
9
#4

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

B
На сайте с 13.02.2008
Offline
262
#5
Asar:
Минусы: искать придется через LIKE %%, соответственно, индекс не сработает, и все будет медленно.

Будет индекс работать, будет, потому что поиск будет по LIKE "foo%".

Предположим, человек ищет категорию2 и все ее дочерние узлы. У этой категории будет ТРИ поля:

Поле - id категории,

Поле - название категории "Категория 2"

Поле - путь к категории "Категория 1|Категория 2", но лучше через id: "id1|id2"

По названию категории (Категория 2) находите ее id (id2) и путь (id1|id2), а дальше делаете запрос: LIKE "id1|id2|%" и получаете список всех дочерних узлов. В этом запросе по этому поле индекс будет работать.

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

CP
На сайте с 12.08.2009
Offline
101
#6
Asar:
Вот и я уж грешным делом подумал, что это ближе не к категориям даже, а каким-нибудь там статейным тегам получается, и многое ко многим сюда можно лепить. Несколько пугает только то, что эти многие исчисляются миллионами...

На милионах и надобности постоянно поиска, вам поисковый движок уже нужен. Sphinx к примеру, c mysql отлично работает.

Но я бы рекомендовал elasticsearch, если с английским проблем нет (чтение доков, на русском очень мало инфы), то с этим движком одно удовольствие работать. Связи можно там хранить, и с мускула уже конкретно что то брать. С таким количеством связей я не работал с elasticsearch, но работал с ним в ключе аля distinct(намного затратнее запрос чем в вашем случае) для поля с массивом значений(более 30 значений) при выборке в 100 000 документов, запрос занимал 20 милисекунд, что чудовещно быстро для впс на которой проект работает.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий