Xpoint
   [напомнить пароль]

получить id раздела по URL (nested sets)

Метки: [без меток]
2006-06-30 17:32:26 [обр] Валера(0/24)[досье]

Используются ЧПУ. Надо получить id текущего раздела по URL.
Анализируется только часть соответствующая REQUEST_URI.

например есть /razdel1/razdel2/somestring/some1/...

и есть виртуальные каталоги razdel1 и razdel2 тогда надо получить id для razdel2,
учитывая что виртуальный каталог /razdel1/razdel2 тоже cуществует

Проще говоря надо получить id последнего существующего виртуального каталога, при соблюдении иерархии, конечно (то есть что в системе существует виртуальный путь до него) .

Есть вариант парсить слева направо, и делать запросы к БД на существование каталога для каждого элемента адреса, до тех пор, пока не наткнемся на несуществующий + проверка на существование полученного виртуального пути. Как скажется это на производительности?

спустя 6 минут [обр] Валера(0/24)[досье]
Есть вариант еще хранить путь до раздела в БД и тем самым находить id раздела за один запрос, но он не видется перспективным из-за того что есть не существующие виртуально пути, которые тоже надо обрабатывать, кроме того надо при вставке узла надо добавлять поле с путем, а при перемещении узла пересчитывать. Короче, не очень хорошо получается.
спустя 1 час 5 минут [обр] Дмитрий Донцов+++(0/68)[досье]
Есть вариант парсить слева направо, и делать запросы к БД на существование каталога для каждого элемента адреса, до тех пор, пока не наткнемся на несуществующий + проверка на существование полученного виртуального пути. Как скажется это на производительности?

плохо скажется...

может так?
http://ctksystem.ru/catalog_8/

8 - id узла, детей котрого надо показать.

спустя 2 дня 15 часов [обр] Валера(0/24)[досье]

Но тут все равно придется каким-то образом проверять весь путь на существование. То, что в адресной строке явно присутствует id нам сильно не облегчит задачу, потому что она как раз в том, чтобы найти этот самый раздел, который надо вывести, то есть на вашем примере http://ctksystem.ru/catalog_8/ - если мы знает что нам нужно показать раздел catalog_8, то можно хранить в БД название этого раздела целиком (catalog_8) и одним запросом извлекать и выводить нужные данные, это не проблема.

Как раз задача состоит в том, чтобы минимальными усилиями (за чем можно меньшее число запросов к БД) распарсить адресную стороку и показать содержание текущего раздела.

А использование id в названии только прибавит проблем: кроме того, что тогда не будет такой гибкости в названии разделов (более дружелюбным выглядет вариант /catalog/cars/honda/ чем /catalog_21/cars_15/honda_953), так как в названии всегда будет идентификатор, еще при изменении БД может поменяться id раздела, и соответственно его URL, предполагаю что для поисковой оптимизации это пагубно скажется.

Еще раз о сути вопроса: есть URL (URI) где слэшами разделены названия разделов, которые хранятся в БД в виде структуры nested sets. Надо за наименьшее количество запросов определить текущий раздел (получить id последнего раздела в максимально длинном пути из URL) учитывая что должна сохраняться иерархия (то есть путь до раздела правильный) не учитывая что стоит после этого раздела, это все будет дальше обрабатываться.

например есть разделы
-catalog


subcat1


subcat11


subcat2


subcat22

и

URL http://mysite.ru/catalog/subcat1/subcat11/somestring/more/...

надо показать subcat11

спустя 1 минуту [обр] Валера(0/24)[досье]
немного исказилось, но смысл понятен, что подчинение такое catalog->subcat1->subcat11
спустя 2 дня 23 часа [обр] Валера(0/24)[досье]
Хорошо, тогда если никто не предлагает лучшего решения, тогда может подскажете альтернативный вариант хранения структуры сайта в БД? Надо только чтобы это была древовидная структура и опять же запросы к страничкам обрабатывались быстро (чтобы быстро находился текущий раздел по адресной строке).
спустя 3 дня [обр] Закиров Руслан(5/343)[досье]
Как я понимаю, у вас проблема в том, что не известно с какого монента заканчиваются эелементы каталога. Мнекажеться, что можно ввести для элементов каталога другой разделитель.
спустя 5 часов [обр] Илья Cтpeльцын aka SelenIT(0/171)[досье]
Валера[досье], а такой вариант с подзапросом разве не подойдет: SELECT id FROM tree WHERE left = (SELECT MAX(left) FROM tree WHERE path IN ('catalog','subcat1','subcat11','somestring','more'))? По идее, он как раз найдет крайний из существующих разделов из переданного списка, а "лишние" параметры проигнорирует...
спустя 7 часов [обр] Валера(0/24)[досье]

Закиров Руслан, вообще говоря здесь не принципиально для каталога рассматривается задача или для простых разделов сайта, в том и другом случаях она сводится к нахождению текущего раздела (id раздела), нужно узнать не с какого момента заканчиваются эелементы каталога, а узнать текущий раздел на сайте (по адресной строке), при том что разделы имеют иерархическую структуру. Разделителем для разделов (простите за тавтологию :))здесь являются обратный слэш '\', это нас устраивает. Например можно было бы сделать так:

у нас разделы хранятся в БД и есть такая вложенность info->about_us->contacts->service
и есть адрес www.mysite.ru/info/about_us/contacts/service/ ,

то мы пробегаем слева направо и сначала находим parent для info
(несложным запросом типа SELECT id, name, level FROM my_tree WHERE left_key <= $left_key AND right_key >= $right_key AND level = $level + 1 ORDER BY left_key), где $left_key, $right_key и $level это для info

 , потом parent для about_us и видим что parent = info, потом parent для contacts (parent=about_us) и так далее пока не наткнемся на несуществующий раздел.

спустя 1 минуту [обр] Валера(0/24)[досье]
 Илья Cтpeльцын, ваш вариант, к сожалению, не подходит, потому что здесь не учитывается иерархия разделов.
спустя 2 часа 43 минуты [обр] Илья Cтpeльцын aka SelenIT(0/171)[досье]
Валера[досье]
Да, я уже понял свою ошибку - это будет работать, только если имена разделов уникальны. Для неуникальных, видимо, придется усложнить запрос до чего-то наподобие такого (вариант для MySQL):
SELECT IFNULL(t5.id, IFNULL(t4.id, IFNULL(t3.id, IFNULL(t2.id, t1.id)))) as result_id
FROM tree t1
LEFT JOIN tree t2
ON t2.left > t1.left AND t2.right < t1.right AND t2.path = 'subcat1'
LEFT JOIN tree t3
ON t3.left > t2.left AND t3.right < t2.right AND t3.path = 'subcat11'
LEFT JOIN tree t4
ON t4.left > t3.left AND t4.right < t3.right AND t4.path = 'somestring'
LEFT JOIN tree t5
ON t5.left > t4.left AND t5.right < t4.right AND t5.path = 'more'
WHERE path = 'catalog'
спустя 3 часа 7 минут [обр] Валера(0/24)[досье]
В условии WHERE вроде должно быть path.t1 ?
То есть здесь каждый LEFT JOIN проверяет родство двух соседних элементов и в итоге мы получим id для последнего элемента в максимально возможной цепочке?
спустя 3 минуты [обр] Валера(0/24)[досье]
вернее t1.path :)
спустя 44 минуты [обр] Илья Cтpeльцын aka SelenIT(0/171)[досье]
Да, именно так, прошу прощения за неточность.
спустя 1 час 55 минут [обр] Валера(0/24)[досье]
Еще детально не тестировал, но думаю вариант предложенный Ильей Cтpeльцыном подходящий. Хотелось бы еще узнать как в плане производительности это будет влиять на сервер, потому что каждое обращение на сайт будет сопровождаться подобным sql-запросом. Ведь там куча LEFT JOIN'ов.
Powered by POEM™ Engine Copyright © 2002-2005