[РЕШЕНО] Знатокам друпал: Views вложенность > 10 (term_with_depth). Или Drupal генерирует страшные запросы.

Главные вкладки

Аватар пользователя fexmusicmutuz@gmail.com fexmusicmutuz@g... 18 сентября 2011 в 16:55

Добрый день!

На сайте есть раздел документов, куда пользователи загружают свои файлы.
Этот раздел выглядит как дерево каталогов, по которому путешествуют пользователи и загружают файлы, создают разделы и т.д.
Дерево каталогов сделано с помощью обыкновенного словаря таксономии.

С помощью views был создан поиск по этим документам, где одним из условий отбора является раздел(выпадающий список с иерархией - term_with_depth).

Все вроде ничего, но при выборе количества подуровней, в которых нужно искать документы максимум можно выбрать 10.
А если нужный документ находится на 3 уровня ниже? Как быть тут?

Ну и это еще не все. Посмотрите, какой запрос сгенерировал друпал:

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
        (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 пунктами.
Но зачем было делать так?
Вот пример запроса, который выбирает документы, независимо от уровня вложенности раздела:

--EXPLAIN ANALYZE
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 такое говно и в нем нет аналитики, то можно написать запрос, который будет работать во всех СУБД.
Перед выполнением основного запроса найти все вложенные разделы

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 * FROM foo

И подставить их в запрос:

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
(
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

Комментарии

Аватар пользователя Orion76 Orion76 18 сентября 2011 в 17:21

Может пересмотреть структуру каталогизации документов?
Например организовать каталог не по 1 словарю а по двум(трем, четырем ....)?
Соответственно и глубина уменьшиться в 2,4,2^n раз?

Да и удобнее это... Даже немогу себе представить, как бы я искал пункт в иерархическом списке в 10 уровней..

Аватар пользователя fexmusicmutuz@gmail.com fexmusicmutuz@g... 18 сентября 2011 в 17:30

orion76 wrote:
Может пересмотреть структуру каталогизации документов?
Например организовать каталог не по 1 словарю а по двум(трем, четырем ....)?
Соответственно и глубина уменьшиться в 2,4,2^n раз?

Да и удобнее это... Даже немогу себе представить, как бы я искал пункт в иерархическом списке в 10 уровней..


Пользователи сами создают эту структуру каталогов, я к этому не прикасаюсь.

Аватар пользователя fexmusicmutuz@gmail.com fexmusicmutuz@g... 18 сентября 2011 в 17:28

Так как не находятся документы, которые находятся в разделах ниже выбранного.

Например:
1--
|
--2
|
--3
|
--4
|
--5
|
--- Документ 1
--- Документ 2

При выборе раздела 1 не находятся документы из 5 раздела.

Аватар пользователя Crea Crea 18 сентября 2011 в 17:42

Если иерархия разделов статичная, то проще всего в своем модуле при сохранении документа помечать его дополнительно терминами-родителями использованных терминов.
Если иерархия меняется, то для исправления запросов на нужные вам можно использовать хук Views для замены запроса, или написать свой хендлер который будет работать так, как вам нужно.

Аватар пользователя fexmusicmutuz@gmail.com fexmusicmutuz@g... 18 сентября 2011 в 20:41

Crea wrote:
Если иерархия разделов статичная, то проще всего в своем модуле при сохранении документа помечать его дополнительно терминами-родителями использованных терминов.
Если иерархия меняется, то для исправления запросов на нужные вам можно использовать хук Views для замены запроса, или написать свой хендлер который будет работать так, как вам нужно.

Спасибо! Изменил запрос через views_query_alter и все заработало. Жаль, конечно, что таким способом решилась проблема.

Аватар пользователя mak-vardugin mak-vardugin 19 сентября 2011 в 18:14

"<a href="mailto:fexmusicmutuz@gmail.com">fexmusicmutuz@gmail.com</a>" wrote:
PgAdmin рисует план выполнения запроса

модненько, эдак тостеры умнее нас скоро станут