В предыдущих статьях я рассказывал, как устанавливать и настраивать Apache Solr для организации поиска на Drupal. Кроме этого мы научились добавлять поля и настройки поискового индекса. В этой статье я расскажу о том, как добавить собственные поля и настройки, если стандартных недостаточно.
Для тех кто не читал предыдущие части, я рекомендую прочесть их для лучшего понимания материала.
- Поиск на Drupal 7 с помощью Apache Solr ч.1 — базовая настройка
- Поиск на Drupal 7 с помощью Apache Solr ч.2 — учимся настраивать индекс
- Поиск на Drupal 7 с помощью Apache Solr ч.3 — учимся добавлять собственные поля и опции в индекс
Поля
Итак начнем с добавления полей. Допустим у нод, которые вы индексируете есть референс на словарь с данными о геолокации. Его структура выглядит так:
Задача — индексировать только значения первого уровня, т.е. области к которым относится нода. Если мы добавим в индекс соответствующее поле, то индексироваться будут все термы, независимо от уровня. Поэтому нам потребуется добавить свое собственное поле. Для этого нам понадобятся две функции. Первая это хук entity_property_info_alter. В этом хуке можно добавить новые поля для сущности. Итак, добавим новое поля для ноды.
/** * Implements hook_entity_property_info_alter. */ function test_search_entity_property_info_alter(&$info) { $info['node']['properties']['geo_first_level'] = array( 'type' => 'text', 'label' => t('Geo 1 level'), 'getter callback' => 'test_search_geo_first_level_getter_callback', ); }
Вторая функция — getter callback, в данном случае test_search_geo_first_level_getter_callback. Она должна возвращать значение для нашего поля в момент индексирования ноды. Это значение будет сохраняться в индексе.
/** * Getter callback. */ function test_search_geo_first_level_getter_callback($item) { if ($geo = field_get_items('node', $item, 'field_geo')) { $parents = taxonomy_get_parents($geo[0]['tid']); if (empty($parents)) { if ($term = taxonomy_term_load($geo[0]['tid'])) { return $term->name; } } } return NULL; }
В качестве $item будет передаваться индексируемая сущность, в нашем случае это объект ноды. Делаем небольшую проверку на то, содержит ли эта нода, терм 1го уровня или нет и возвращаем имя терма в качестве индексируемого значения.
Теперь заходим в настройки индекса и выбираем вкладку Fields.
Наше новое поле уже доступно для индексирования. Не забудьте добавить его в список полей, по которым можно искать в настройках view.
Иногда может потребоваться индексировать несколько значений для поля. Для этого в хуке entity_property_info_alter укажите ‘type’ => ‘list’, а в геттер колбеке нужно будет возвращать массив значений.
Например return array('Москва', 'Санкт-Петербург', 'Новосибирск');
Фильтры
Теперь попробуем добавить фильтр, по которому можно будет отбирать ноды для индексирования. Фильтр будет выполнять аналогичную функцию — позволять индексировать только те ноды, у которых есть референс на терм первого уровня из словаря geo. Для этого в хуке search_api_alter_callback_info объявим наш фильтр.
/** * Implements hook_search_api_alter_callback_info(). */ function test_search_search_api_alter_callback_info() { $callbacks['search_api_alter_geo_level'] = array( 'name' => t('Filter by level of geo'), 'description' => t('Index only nodes with first level of term from vocabulary geo'), 'class' => 'SearchApiAlterGeoLevelFilter', // Filters should be executed first. 'weight' => -10, ); return $callbacks; }
Файл с классом фильтра я расположил в папке includes модуля test_search. Не забудьте подключить его в .info файле вашего модуля. Например так: files[] = includes/callback_geo_level.inc
Ниже приведен код самого фильтра
<?php /** * Search API data alteration callback that adds an URL field for all items. */ class SearchApiAlterGeoLevelFilter extends SearchApiAbstractAlterCallback { public function alterItems(array &$items) { foreach ($items as $id => $item) { if ($geo = field_get_items('node', $item, 'field_geo')) { $parents = taxonomy_get_parents($geo[0]['tid']); // If term has parents. if (!empty($parents)) { unset($items[$id]); } } } } public function supportsIndex(SearchApiIndex $index) { return $index->item_type === 'node'; } }
В функции alterItems мы просто исключаем элементы, которые имеют термы не первого уровня. Эти элементы не будут проиндексированы.
Чтобы включить фильтр, нужно почистить кеш и перейти на вкладке workflow в настройках индекса.
После того включения фильтра необходимо переиндексировать контент заново. Теперь в индекс попадут лишь те ноды, у которых есть терм словаря первого уровня.
ссылка на оригинал статьи http://habrahabr.ru/post/178285/
Добавить комментарий