Добрый день!
На сайте есть раздел документов, куда пользователи загружают свои файлы.
Этот раздел выглядит как дерево каталогов, по которому путешествуют пользователи и загружают файлы, создают разделы и т.д.
Дерево каталогов сделано с помощью обыкновенного словаря таксономии.
С помощью views был создан поиск по этим документам, где одним из условий отбора является раздел(выпадающий список с иерархией - term_with_depth).
Все вроде ничего, но при выборе количества подуровней, в которых нужно искать документы максимум можно выбрать 10.
А если нужный документ находится на 3 уровня ниже? Как быть тут?
Ну и это еще не все. Посмотрите, какой запрос сгенерировал друпал:
'node' AS field_data_field_docs_file_node_entity_type, 'node' AS field_data_field_ndoc_category_node_entity_type
FROM
node node
LEFT JOIN field_data_field_ndoc_category field_data_field_ndoc_category ON node.nid = field_data_field_ndoc_category.entity_id
AND (field_data_field_ndoc_category.entity_type = 'node' AND field_data_field_ndoc_category.deleted = '0')
LEFT JOIN taxonomy_term_data taxonomy_term_data_field_data_field_ndoc_category ON
field_data_field_ndoc_category.field_ndoc_category_tid = taxonomy_term_data_field_data_field_ndoc_category.tid
WHERE (( (node.type IN ('norm_document'))
AND (node.nid IN
(SELECT tn.nid AS nid
FROM
taxonomy_index tn
LEFT OUTER JOIN taxonomy_term_hierarchy th ON th.tid = tn.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th1 ON th.parent = th1.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th2 ON th1.parent = th2.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th3 ON th2.parent = th3.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th4 ON th3.parent = th4.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th5 ON th4.parent = th5.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th6 ON th5.parent = th6.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th7 ON th6.parent = th7.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th8 ON th7.parent = th8.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th9 ON th8.parent = th9.tid
LEFT OUTER JOIN taxonomy_term_hierarchy th10 ON th9.parent = th10.tid
WHERE ( (tn.tid = '89') OR (th1.tid = '89') OR (th2.tid = '89') OR (th3.tid = '89') OR (th4.tid = '89') OR (th5.tid = '89') OR (th6.tid = '89') OR (th7.tid = '89') OR (th8.tid = '89') OR (th9.tid = '89') OR (th10.tid = '89') ))) ))
LIMIT 25 OFFSET 0
Теперь понятно почему они решили ограничиться 10 пунктами.
Но зачем было делать так?
Вот пример запроса, который выбирает документы, независимо от уровня вложенности раздела:
SELECT node.title AS node_title, node.nid AS nid, 'node' AS field_data_field_ndoc_name_node_entity_type,
'node' AS field_data_field_docs_file_node_entity_type, 'node' AS field_data_field_ndoc_category_node_entity_type
FROM
node node
LEFT JOIN field_data_field_ndoc_category field_data_field_ndoc_category ON node.nid = field_data_field_ndoc_category.entity_id
AND (field_data_field_ndoc_category.entity_type = 'node' AND field_data_field_ndoc_category.deleted = '0')
LEFT JOIN taxonomy_term_data taxonomy_term_data_field_data_field_ndoc_category ON
field_data_field_ndoc_category.field_ndoc_category_tid = taxonomy_term_data_field_data_field_ndoc_category.tid
WHERE (( (node.type IN ('norm_document'))
AND (node.nid IN
(WITH RECURSIVE foo AS
(SELECT tid FROM taxonomy_term_hierarchy WHERE parent = 89
UNION ALL
SELECT h.tid FROM taxonomy_term_hierarchy h
JOIN foo ON foo.tid = h.parent)
SELECT tn.nid FROM foo JOIN taxonomy_index tn ON tn.tid = foo.tid)
) ))
LIMIT 25 OFFSET 0
Правда есть одно НО - работает только в PostgreSQL 8.4 и выше. Ну если MySQL такое говно и в нем нет аналитики, то можно написать запрос, который будет работать во всех СУБД.
Перед выполнением основного запроса найти все вложенные разделы
(SELECT tid FROM taxonomy_term_hierarchy WHERE parent = 89
UNION ALL
SELECT h.tid FROM taxonomy_term_hierarchy h
JOIN foo ON foo.tid = h.parent)
SELECT * FROM foo
И подставить их в запрос:
'node' AS field_data_field_docs_file_node_entity_type, 'node' AS field_data_field_ndoc_category_node_entity_type
FROM
node node
LEFT JOIN field_data_field_ndoc_category field_data_field_ndoc_category ON node.nid = field_data_field_ndoc_category.entity_id
AND (field_data_field_ndoc_category.entity_type = 'node' AND field_data_field_ndoc_category.deleted = '0')
LEFT JOIN taxonomy_term_data taxonomy_term_data_field_data_field_ndoc_category ON
field_data_field_ndoc_category.field_ndoc_category_tid = taxonomy_term_data_field_data_field_ndoc_category.tid
WHERE (( (node.type IN ('norm_document'))
AND (node.nid IN
(
SELECT tn.nid FROM taxonomy_index tn WHERE tn.tid IN (100,61,44,62,63,91,65,67,64,68,66,97,95,98,92,93,99,94
))
) ))
LIMIT 25 OFFSET 0
Главный вопрос:
Как вывести все документы, независимо от уровня вложенности? Т.е. depth = infinity
Комментарии
Аргумент "термин без глубины" чем не подходит ?
Может пересмотреть структуру каталогизации документов?
Например организовать каталог не по 1 словарю а по двум(трем, четырем ....)?
Соответственно и глубина уменьшиться в 2,4,2^n раз?
Да и удобнее это... Даже немогу себе представить, как бы я искал пункт в иерархическом списке в 10 уровней..
Пользователи сами создают эту структуру каталогов, я к этому не прикасаюсь.
Так как не находятся документы, которые находятся в разделах ниже выбранного.
Например:
1--
|
--2
|
--3
|
--4
|
--5
|
--- Документ 1
--- Документ 2
При выборе раздела 1 не находятся документы из 5 раздела.
Если иерархия разделов статичная, то проще всего в своем модуле при сохранении документа помечать его дополнительно терминами-родителями использованных терминов.
Если иерархия меняется, то для исправления запросов на нужные вам можно использовать хук Views для замены запроса, или написать свой хендлер который будет работать так, как вам нужно.
Спасибо! Изменил запрос через views_query_alter и все заработало. Жаль, конечно, что таким способом решилась проблема.
Объясните пожалуйста чуть по подробнее.
Прошу прощения, за отклонение от темы, но чем нарисованы красивые планы выполнения запросов?
Подпишусь, пожалуй
сурьезный подход, аж с илююстрациями
Это PgAdmin рисует план выполнения запроса.
subscribe
модненько, эдак тостеры умнее нас скоро станут