Поиск на Drupal 7 с помощью Apache Solr ч.3 — учимся добавлять собственные поля и опции в индекс

от автора


В предыдущих статьях я рассказывал, как устанавливать и настраивать Apache Solr для организации поиска на Drupal. Кроме этого мы научились добавлять поля и настройки поискового индекса. В этой статье я расскажу о том, как добавить собственные поля и настройки, если стандартных недостаточно.
Для тех кто не читал предыдущие части, я рекомендую прочесть их для лучшего понимания материала.

Поля

Итак начнем с добавления полей. Допустим у нод, которые вы индексируете есть референс на словарь с данными о геолокации. Его структура выглядит так:

Задача — индексировать только значения первого уровня, т.е. области к которым относится нода. Если мы добавим в индекс соответствующее поле, то индексироваться будут все термы, независимо от уровня. Поэтому нам потребуется добавить свое собственное поле. Для этого нам понадобятся две функции. Первая это хук 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *