Категория:
Опубликовано:

Индексация кастомных значений в Search API

Search API Index

Search API - известный, удобный и полезный инструмент для сайта на Drupal.

"Из коробки" - он работает со всеми полями сущностей, будь то ноды или самописный product-entity.

Но что делать, если нужно добавить возможность индексации, а в дальнейшем фильтрации и составления фасетов по нестандартным значениям? Программировать, конечно же! )) И делается это достаточно просто.

Добавляем в индекс собственные поля сущностей с помощью Search API.

Нам понадобится всего лишь один хук - hook_entity_property_info_alter и коллбек к нему.

Вот как это выглядит:

/**
 * Implements hook_entity_property_info_alter().
 */
function ИМЯ_МОДУЛЯ_entity_property_info_alter(&$info) {
  $info['node']['properties']['ИМЯ_СВОЙСТВА'] = array(
    // Тип данных по умолчанию
    'type'            => 'decimal',
    // Название свойства
    'label'           => t('Property name'),
    // Описание свойства
    'description'     => t('Property description'),
    // Коллбек отвечающий за получение данных
    'getter callback' => 'my_property_getter_callback',
  );
}

/**
 * Getter callback for my_property.
 * 
 * Здесь получаем нужные нам данные и отправляем в индекс
 *   $item - объект сущности.
 *   Возвращаем данные для индексации.
 */
function my_property_getter_callback($item) {
  return $item->my_property;
}

Рассмотрим подробнее.

Как это работает

Если мы посмотрим внутреннюю часть работы нашего модуля, можем увидеть следующую картину - ссылка на переменную $info, к которой мы добавляем свойства в хуке, содержит список сущностей доступных на сайте:

entitys

Которые, в свою очередь, содержат список типов сущностей (bundles) и список доступных свойств (properties):

bundles properties

Именно в список свойств мы добавляем новое.

Давайте, на примере, добавим новое свойство - Node ID.

Вызываем, в своем модуле, hook_entity_property_info_alter:

/**
 * Implements hook_entity_property_info_alter().
 */
function module_entity_property_info_alter(&$info) {
  $info['node']['properties']['my_property'] = array(
  $info['node']['properties']['my_property'] = array(
    'type'            => 'integer',
    'label'           => t('My node NID'),
    'description'     => t('My custom field Node ID'),
    'getter callback' => 'my_property_getter_callback',
  );
}
  • module - меняем на имя своего модуля
  • type - тип данных
  • label - название
  • description - описание (не обязательно)
  • getter callback - коллбек
  • полный список свойств и типов данных есть в описании хука hook_entity_property_info

Сейчас, если открыть страницу настроек полей индекса - уже можно увидеть наше свойство:

fields settings

Теперь напишем callback-функцию для нашего поля:

/**
 * Getter callback for my_property.
 */
function my_property_getter_callback($item) {
  return $item->nid;
}

В переменной $item содержится экземпляр текущего объекта. В нашем случае - объекта ноды.

Объект загружается полностью, поэтому если Вы переопределяли его загрузку с помощью хуков entity_load (node_load, user_load...) - все данные будут там.

При необходимости - делайте проверку перед возвратом.

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

P.S. После включения свойства, если используется фасеточный поиск, среди фасетов появится и новый - со свеже-добавленным свойством. И после переиндексации его можно будет успешно применять.

Удачи!

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

Комментарии

Господа. Можно ли в фильтре, созданном с помощь search api, facet api, coommerce search api выбрать несколько пунктов сразу? НА пример, фильтр по бренду - выбрать несколько брендов. Если да, то как настроить. спасибо