Hybris: поиск Solr по составному полю

Понадобилось как-то в SAP Hybris настроить поиск по составному полю (состоящему из нескольких атрибутов продукта). Так, чтобы при запросе вида «желтый ботинок» в листинге товаров сначала выдавались не просто товары желтого цвета, а именно желтые ботинки (а затем — остальные ботинки). Решить это регулировкой коэффициентов усиления поиска по отдельным свойствам (boost) не удалось, пришлось городить огород с созданием и индексацией составного поля.

Модель товара ProductModel

Итак, в предлагаемом примере товар (Product) имеет два атрибута (помимо прочих), по которым надо искать в связке:

  • Name — название товара
  • Color — его цвет

Создание Value Resolver

В простом случае (а рассматривается именно такой), resolver может выглядеть следующим образом:
[cc lang=»java» line_numbers=»false»]
public class ProductNameColorValueResolver extends AbstractApparelStyleValueResolver {
@Override
protected void addFieldValues(InputDocument inputDocument, IndexerBatchContext indexerBatchContext,
IndexedProperty indexedProperty, ProductModel model, ValueResolverContext valueResolverContext)
throws FieldValueProviderException
{
if (model != null && model.getName() != null && model.getColor() != null) {
List < String > fieldNames = List.of(
model.getName(),
model.getColor().getName(),
);
for (String name : fieldNames) {
inputDocument.addField(indexedProperty, name, valueResolverContext.getFieldQualifier());
}
}
}
}
[/cc]
Что здесь нужно помнить: структура продуктов может содержать несколько уровней. Например, отдельно — Товар (родитель) и отдельно — Товар с Цветом (потомок). В этом случае в resolver попадает сущность «нижнего» уровня, которая может не содержать всех требуемых атрибутов. То есть, возможна ситуация, когда атрибут Color нужно получить непосредственно из сущности, пришедшей в resolver, а атрибут Name — из её родителя.

Добавление Value Resolver в контекст приложения

Чтобы resolver работал — нужно не забыть добавить его в контекст приложения. Обычным для Spring с XML-конфигурацией образом — определить бин в spring.xml
[cc lang=»xml» line_numbers=»false»]

[/cc]

Добавление индексируемого свойства в Solr

Наконец, необходимо добавить новое составное поле в индексируемые свойства товара, с которыми работает поиск Solr. Это можно сделать вручную при помощи BackOffice, но проще и удобней — составить impex и затем импортировать его из Hybris Administration Console (HAC).
[cc lang=»text» line_numbers=»false»]
$solrIndexedType = myProductType
INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=true];name[unique=true];type(code);sortableType(code);currency[default=false];localized[default=false];multiValue[default=false];useForSpellchecking[default=false];useForAutocomplete[default=false];fieldValueProvider;valueProviderParameters[map-delimiter=|];ftsPhraseQuery[default=false];ftsPhraseQueryBoost;ftsQuery[default=false];ftsQueryBoost;ftsFuzzyQuery[default=false];ftsFuzzyQueryBoost;ftsWildcardQuery[default=false];ftsWildcardQueryType(code)[default=POSTFIX];ftsWildcardQueryBoost;ftsWildcardQueryMinTermLength;
;$solrIndexedType; productNameColorMultiField; text;;; true; true; true; true; productNameColorValueResolver;; true; 40;; ; true; 20;;;;
[/cc]
Из интересного здесь — указание ранее описанного бина productNameColorValueResolver в качестве fieldValueProvider и создание начальных коэффициентов усиления (boost) для разных типов поиска — ftsPhraseQueryBoost (40), ftsFuzzyQueryBoost (20). Можно задать boost и для остальных видов поиска. Впрочем, в дальнейшем эти коэффициенты (как и остальные атрибуты индексируемого свойства) не сложно поменять в BackOffice.

Индексируемое свойство Solr — итоги

Таким способом можно добавить в индекс Solr произвольное поле, по которому будет производиться поиск, отсутствующее в модели товара — без изменения самой модели. И задать этому полю коэффициенты усиления для ранжирования результатов выполнения поискового запроса. Пример не самый сложный, но общий принцип иллюстрирует. На этом всё :-)

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

Ваш адрес email не будет опубликован.