Фильтрация нод по терминам нескольких словарей

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

Аватар пользователя Zigs Zigs 1 октября 2012 в 23:25

Коллеги, снова поднимаю вопрос о фильтрации нод по терминам нескольких словарей... одновременно.
Поиском искал, не нашел. Топиков много, а вот решений ни одного. Как известно, по умолчанию, View не умеет делать AND c несколькими терминами.

Вкратце задача такова:
Есть пара иерархических словарей.
Например:
1. Техника
-- Авто
-- Грузовые
-- Легковые
-- Велосипеды
-- Два колеса
-- Моноциклы

2. Цвет
-- Темный
-- Синий
-- Черный
-- Светлый
--Желтый
--Белый

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

Ставил модуль Taxonomy Filter с его аналогами, но там нет иерархии. Представление выдает только четкие совпадения терминов.

Подскажите, как реализовать такой функционал? Интересует любое решение, необязательно на основе представлений.
Буду благодарен за любую инфу и помощь.

Спасибо.

Комментарии

Аватар пользователя Zigs Zigs 4 октября 2012 в 9:49

Раз никто ничего не ответил, то предложу свое решение. Оно оказалось не сильно простым, но ничего лучшего придумать-найти пока не удалось.

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

Итак:

Ручками сделал в базе таблицу со следующими полями (taxonomy_term_node_row):
1. nid - идентификатор ноды
2. term1 - идентификатор термина из одного словаря
3. term2 - идентификатор термина из второго словаря

В модуле отхучил node_insert, где:
$terms_voc1 = taxonomy_get_parents(term1);
$terms_voc2 = taxonomy_get_parents(term2);

foreach ($terms_voc1 as $t1):
foreach ($term_voc2 as $t2):
... заполнение таблицы taxonomy_term_node_row
endforeach;
endforeach;

Соответственно еще отхучил node_delete, чтобы удалять это хозяйство при удалении ноды.

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

Теперь возникли еще некоторые вопросы:
На данный момент выборка осуществляется текстовым запросом через db_query, т.е. без views.

Не могу для себя решить по какому пути двигаться дальше:
то ли оставить db_query, но это придется писать свою обработку постраничной навигации, свою темизацию, кеширование,
то ли каким-то образом попробовать интегрировать эту таблицу в views. С разработкой для views не сильно знаком, буду раз за любые ссылки.

Уважаемые, наставьте на путь истинный Smile

Аватар пользователя divined divined 4 октября 2012 в 9:58

Views прекрасно фильтрует по двум и более словарям и терминам, там остается только проблема с сортировкой, но и она решается.

Аватар пользователя divined divined 4 октября 2012 в 10:04

Чтобы добавить иерархию можно было просто сделать хук на views. В любом случае, я понимаю что не вовремя, но если не понравится ваше решение, сможете поэкспериментировать по другому пути.

Аватар пользователя Zigs Zigs 4 октября 2012 в 12:21

"divined" wrote:
Views прекрасно фильтрует по двум и более словарям и терминам, там остается только проблема с сортировкой, но и она решается.

Прекрасно фильтрует если OR, т.е. выбрать ноды, которые связаны с одним из указанных терминов, независимо от словаря. Мне же нужен AND.
Если знаете как это сделать просто настройкой views, подскажите пожалуйста.

"divined" wrote:
Чтобы добавить иерархию можно было просто сделать хук на views.

Опять же, можно поподробнее...

Аватар пользователя divined divined 4 октября 2012 в 14:07

Давайте подробнее:

1. Словари должны быть такие:

1. Техника
-- Авто
---- Грузовые
---- Легковые
-- Велосипеды
---- Два колеса
-- Моноциклы

2. Цвет
-- Темный
---- Синий
---- Черный
-- Светлый
---- Желтый
---- Белый

т.е. Синий и Черный должны быть дочерними к Темному.

Почему прекрасно работает? Давайте отступим от Views и обратим внимание на БД.
Таблица taxonomy_index содержит записи NID TID, и не важно из какого словаря этот термин.

Что делает VIEWS - строит запрос к БД и выбирает NID из этой таблицы, к указанному вами TID.

-----

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

Это можно изменить поставив модуль hierarchical select, у которого в настройках есть функция сохранения полного пути термина.

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

И Вьюс будет отрабатывать правильно.

----

На пальцах:

Создали
1. грузовик синего цвета - (nid 100) (грузовик TID 10, темный TID 20, синий TID 21)

taxonomy_index в первом случае
NID TID
100 10 //термин первого словаря
100 21 //дочерний термин второго словаря

taxonomy_index во втором случае
NID TID
100 10 //термин первого словаря
100 20 //т.е. добавился родительский термин второго словаря
100 21 //дочерний термин

2. Грузовик черного цвета - (nid 101) (грузовик TID 10, темный TID 20, черный TID 22)
taxonomy_index в первом случае
NID TID
100 10 //термин первого словаря
100 21 //дочерний термин второго словаря
101 10 //термин первого словаря
101 22 //дочерний термин второго словаря

taxonomy_index во втором случае
NID TID
100 10 //термин первого словаря
100 20 //родительский термин второго словаря
100 21 //дочерний термин второго словаря
101 10 //термин первого словаря
101 20 //родительский термин второго словаря
100 21 //дочерний термин второго словаря

Так понятно?

Аватар пользователя Zigs Zigs 4 октября 2012 в 23:25

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

Аватар пользователя divined divined 5 октября 2012 в 0:04

Поставьте два фильтра, или два аргумента, в зависимости от того фильтруете вы автоматически по адресу или выбирает пользователь.

Если аргумент, то получится адрес вида: taxonomy/term/$tid1/$tid2

Если пользователь щелкает на фильтре, то там все автоматом подставится.