Pull to refresh

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

Reading time3 min
Views7.4K

В предыдущих статьях я рассказывал, как устанавливать и настраивать 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 в настройках индекса.



После того включения фильтра необходимо переиндексировать контент заново. Теперь в индекс попадут лишь те ноды, у которых есть терм словаря первого уровня.
Tags:
Hubs:
Total votes 9: ↑8 and ↓1+7
Comments2

Articles