Статьи

Solr и автозаполнение (часть 1)

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

Показатель

Предположим, вы хотите показать некоторые подсказки пользователю в онлайн-магазине, например, вы хотите показать название продукта. Предположим, что наш индекс состоит из следующих полей:

<field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
<field name="name" type="text" indexed="true" stored="true" multiValued="false" />
<field name="description" type="text" indexed="true" stored="true" multiValued="false" />

Тип текста определяется следующим образом:

<fieldType name="text" class="solr.TextField" positionIncrementGap="100">
 <analyzer>
  <tokenizer class="solr.WhitespaceTokenizerFactory"/>
  <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
  <filter class="solr.LowerCaseFilterFactory"/>
 </analyzer>
</fieldType>

конфигурация

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

Подсказка отдельных слов, составляющих имя

В случае отдельных слов мы должны использовать поле с токенами. В нашем случае поля с именем name будет достаточно. Тем не менее, обратите внимание, что если вы хотите использовать, например, stemming, вы должны определить другой тип, который не использует stemming из-за того, как этот анализ работает с содержимым поля.

Запрашивая полное имя

Для полных названий предложений по продуктам нам нужна другая конфигурация поля — лучшим для этого будет поле без тегов. Но мы не можем использовать строковое поле для этого. Для этого мы определим поле следующим образом:

<field name="name_auto" type="text_auto" indexed="true" stored="true" multiValued="false" />

Этот тип определяется следующим образом:

<fieldType name="text_auto" class="solr.TextField">
 <analyzer>
  <tokenizer class="solr.KeywordTokenizerFactory"/>
  <filter class="solr.LowerCaseFilterFactory"/>
 </analyzer>
</fieldType>

Чтобы не изменять формат данных , мы также добавить соответствующее определение копирования информации :

<copyField source="name" dest="name_auto" />

Как мы это используем?

Чтобы использовать подготовленные нами данные, мы используем довольно простой запрос:

q=*:*&facet=true&facet.field=FIELD&facet.mincount=1&facet.prefix=USER_QUERY

Где:

  • ПОЛЕ — поле, на основании которого мы намерены вносить предложения. В нашем случае это поле с именем name или name_string .
  • USER_QUERY — буквы, введенные пользователем.

Стоит отметить, что здесь добавлен параметр row = 0, чтобы показать только результат огранки без результатов запроса. Конечно, это не обязательно.

Пример запроса будет выглядеть так:

fl=id,name&rows=0&q=*:*&facet=true&facet.field=name_auto&facet.mincount=1&facet.prefix=har

Результат этого запроса может выглядеть так:

<response>
 <lst name="responseHeader">
  <int name="status">0</int>
  <int name="QTime">0</int>
 </lst>
 <result name="response" numFound="4" start="0"/>
 <lst name="facet_counts">
  <lst name="facet_queries"/>
  <lst name="facet_fields">
   <lst name="name_auto">
    <int name="hard disk">1</int>
    <int name="hard disk samsung">1</int>
    <int name="hard disk seagate">1</int>
    <int name="hard disk toshiba">1</int>
   </lst>
  </lst>
  <lst name="facet_dates"/></lst>
</response>

Дополнительные возможности

Стоит упомянуть дополнительные возможности, которые присущи этому методу.

Первая возможность — показать пользователю дополнительную информацию, такую ​​как количество результатов, которые вы получаете, когда выбираете соответствующую подсказку. Если вы хотите показать такую ​​информацию, это, безусловно, будет интересным вариантом.

Следующая вещь — сортировка с использованием параметра facet.sort . В зависимости от ваших потребностей, мы можем отсортировать результаты по количеству документов (поведение по умолчанию, параметр имеет значение true ) или по алфавиту (значение false ).

Мы можем ограничить предложения теми, которые имеют больше результатов, чем указанное число. Чтобы воспользоваться этой возможностью, передайте параметр facet.mincount с соответствующим номером.

И, на мой взгляд, самым большим преимуществом этого метода является возможность получать только те предложения, которые соответствуют не только буквам, набираемым пользователем, но и некоторым другим параметрам, например категории. Например, мы хотим показать подсказки для пользователя, который находится в разделе домашнего хозяйства нашего магазина. Мы подозреваем, что в данный момент пользователь не будет интересоваться продуктами типа DVD, и поэтому мы добавляем параметр fq = отдела: homeAppliances (при условии, что у нас есть такой отдел). После такого измененного запроса вы не получите подсказки, сгенерированные из всего индекса, мы только сузим подсказки для выбранного отдела.

Несколько слов в конце

Как и у другого метода, этот тоже имеет свои преимущества и недостатки. Преимущество этого решения заключается в его простоте использования, отсутствии необходимости в дополнительных компонентах, а также в том, что подсказки к результатам можно легко сузить, чтобы они создавались только из тех документов, которые соответствуют запросу, введенному пользователем. Большим плюсом является то, что метод включает количество результатов, которые будут отображаться после выбора подсказки (конечно, с теми же параметрами поиска). Для недостатков, безусловно, необходимо иметь дополнительные типы и поля, достаточно ограниченные возможности и нагрузку, вызванную использованием механизма огранки.

Следующая запись об автозаполнении будет расширена и покажет дополнительные методы генерации подсказок с использованием Solr.