Статьи

Использование Solarium с SOLR для поиска — Дополнительно

Это четвертая и последняя часть серии об использовании реализации поиска Apache SOLR вместе с Solarium, библиотекой PHP для интеграции ее в ваше приложение, как если бы оно было встроенным.

В первых трех частях мы установили и настроили SOLR и Solarium и начали создавать пример приложения для поиска фильмов. Мы также посмотрели на граненый поиск.

Мы собираемся завершить серию, рассмотрев некоторые более продвинутые функции SOLR и их использование в Solarium.

Подсветка результатов с помощью SOLR

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

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

$hl = $query->getHighlighting(); $hl->setFields(array('title', 'synopsis')); $hl->setSimplePrefix('<strong>'); $hl->setSimplePostfix('</strong>'); 

В качестве альтернативы, чтобы добавить цвет фона:

 $hl = $query->getHighlighting(); $hl->setFields(array('title', 'synopsis')); $hl->setSimplePrefix('<span style="background:yellow;">'); $hl->setSimplePostfix('</span>'); 

Или вы можете использовать настройки для каждого поля:

 $hl = $query->getHighlighting(); $hl->getField('title')->setSimplePrefix('<strong>')->setSimplePostfix('</strong>'); $hl->getField('synopsis')->setSimplePrefix('<span style="background:yellow;">')->setSimplePostfix('</span>'); 

После того, как вы настроили компонент подсветки в своей реализации поиска, нужно еще немного поработать, чтобы отобразить его в представлении результатов поиска.

Сначала вам нужно извлечь выделенный документ из подсвечивающего компонента по идентификатору:

 $highlightedDoc = $highlighting->getResult($document->id); 

Теперь вы можете получить доступ ко всем выделенным полям, просматривая их как свойства выделенного документа:

 if($highlightedDoc){ foreach($highlightedDoc as $field => $highlight) { echo implode(' (...) ', $highlight) . '<br/>'; } } 

Или вы можете использовать getField() :

 if($highlightedDoc){ $highlightedTitle = $highlightedDoc->getField('title'); } 

Выделенные поля не просто возвращают текст, но вместо этого они возвращают массив «фрагментов» текста. Если нет совпадений для этого конкретного поля — например, если ваш поиск соответствовал названию, но не синопсису — тогда этот массив будет пустым.

Код выше вернет максимум один фрагмент. Чтобы изменить это поведение, вы можете использовать метод setSnippets() :

 $hl = $query->getHighlighting(); $hl->setSnippets(5); // . . . as before . . . 

Например, предположим, вы ищете слово «звезда». Один из результатов имеет краткий обзор, который гласит:

Это событие, которое нельзя пропустить, представит один из самых запоминающихся моментов в истории телевидения и эксклюзивные ролики о создании «Лучшего из обоих миров» и «Звездный путь: сезон 3 следующего поколения». Набор в 24 веке, «Следующее поколение» был создан Джином Родденберри через 20 лет после оригинальной серии Star Trek. Следующее поколение стало самой продолжительной серией франшизы Star Trek, состоящей из 178 эпизодов за 7 сезонов. «Звездный путь: следующее поколение — лучшее из обоих миров» — это первая возможность увидеть «Лучшее из обоих миров», один из величайших телевизионных эпизодов всех времен, как великолепно обновленную полнометражную функцию в избранных кинотеатрах по всей стране.

Массив синопсиса выделенного документа будет содержать три элемента:

  • история и эксклюзивные клипы о создании «Лучшего из обоих миров» и « Звездный путь: следующее поколение»
  • после оригинальной серии Star Trek. Следующее поколение стало самой продолжительной серией звезды
  • Трек франшизы, состоящий из 178 эпизодов за 7 сезонов. Star Trek: следующее поколение — лучшее из

Один из способов отображения нескольких фрагментов — это их implode , например:

 implode(' ... ', $highlightedDoc->getField('synopsis')) 

Это приводит к следующему:

история и эксклюзивные клипы о создании «Лучшего из обоих миров» и « Звездный путь: следующее поколение»… после оригинальной серии « Звездный путь». Следующее поколение стало самой продолжительной серией франшизы Star… Trek, состоящей из 178 эпизодов за 7 сезонов. Star Trek: следующее поколение — лучшее из

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

Теперь, когда мы рассмотрели, как использовать выделение, его интеграция в наше приложение для поиска фильмов должна быть простой.

Первое, что нужно сделать, это изменить app/controllers/HomeController.php , добавив следующее непосредственно перед запуском поиска:

 // Get highlighting component, and apply settings $hl = $query->getHighlighting(); $hl->setSnippets(5); $hl->setFields(array('title', 'synopsis')); $hl->setSimplePrefix('<span style="background:yellow;">'); $hl->setSimplePostfix('</span>'); // Execute the query and return the result $resultset = $this->client->select($query); 

Тогда результаты поиска, которые вы запомните в app/views/home/index.blade.php становятся:

 @if (isset($resultset)) <header> <p>Your search yielded <strong>{{ $resultset->getNumFound() }}</strong> results:</p> <hr /> </header> @foreach ($resultset as $document) <?php $highlightedDoc = $highlighting->getResult($document->id); ?> <h3>{{ (count($highlightedDoc->getField('title'))) ? implode(' ... ', $highlightedDoc->getField('title')) : $document->title }}</h3> <dl> <dt>Year</dt> <dd>{{ $document->year }}</dd> @if (is_array($document->cast)) <dt>Cast</dt> <dd>{{ implode(', ', $document->cast) }}</dd> @endif </dl> {{ (count($highlightedDoc->getField('synopsis'))) ? implode(' ... ', $highlightedDoc->getField('synopsis')) : $document->synopsis }} @endforeach @endif 

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

Предложение — Добавление автозаполнения

Компонент Suggester используется для предложения условий запроса на основе неполного ввода запроса. По сути, он проверяет индекс по заданному полю и извлекает условия поиска, которые соответствуют определенному шаблону. Затем вы можете заказать эти предложения по частоте, чтобы повысить актуальность поиска.

Чтобы настроить solrconfig.xml , нам нужно настроить ее в файле solrconfig.xml . Откройте его и поместите следующий фрагмент XML где-то рядом с другими объявлениями <searchComponent> :

 <searchComponent class="solr.SpellCheckComponent" name="suggest"> <lst name="spellchecker"> <str name="name">suggest</str> <str name="classname">org.apache.solr.spelling.suggest.Suggester</str> <str name="lookupImpl">org.apache.solr.spelling.suggest.tst.TSTLookupFactory</str> <str name="field">title</str> <!-- the indexed field to derive suggestions from --> <float name="threshold">0.005</float> <str name="buildOnCommit">true</str> </lst> </searchComponent> <requestHandler class="org.apache.solr.handler.component.SearchHandler" name="/suggest"> <lst name="defaults"> <str name="spellcheck">true</str> <str name="spellcheck.dictionary">suggest</str> <str name="spellcheck.onlyMorePopular">true</str> <str name="spellcheck.count">5</str> <str name="spellcheck.collate">true</str> </lst> <arr name="components"> <str>suggest</str> </arr> </requestHandler> 

Вы заметите несколько ссылок на «проверку орфографии», но это просто потому, что компонент Suggester многократно использует большую часть этой функциональности.

Важный момент, на который следует обратить внимание — это элемент <str name="field"> , который сообщает компоненту, что мы хотим использовать поле заголовка, на котором основываются наши предложения.

Перезапустите SOLR, и теперь вы можете попробовать выполнить запрос предложения через веб-браузер:

 `http://localhost:8983/solr/suggest?q=ho` 

(Возможно, вам придется изменить номер порта, в зависимости от того, как вы настроили SOLR)

Вывод должен выглядеть примерно так:

 <?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"> <int name="status">0</int> <int name="QTime">0</int> </lst> <lst name="spellcheck"> <lst name="suggestions"> <lst name="ho"> <int name="numFound">4</int> <int name="startOffset">0</int> <int name="endOffset">2</int> <arr name="suggestion"> <str>house</str> <str>houses</str> <str>horror</str> <str>home</str> </arr> </lst> <str name="collation">house</str> </lst> </lst> </response> 

Как видите, SOLR возвратил четыре возможных совпадения для «ho» — использование * ho **, использование ** ho **, ** ho ** rror и ** ho ** me. Несмотря на то, что дом и ужас находятся перед домом в алфавите, дом появляется первым благодаря тому, что он является одним из самых распространенных поисковых терминов в нашем индексе.

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

Сначала определите маршрут:

 public function getAutocomplete() { // get a suggester query instance $query = $client->createSuggester(); $query->setQuery(Input::get('term')); $query->setDictionary('suggest'); $query->setOnlyMorePopular(true); $query->setCount(10); $query->setCollate(true); // this executes the query and returns the result $resultset = $client->suggester($query); $suggestions = array(); foreach ($resultset as $term => $termResult) { foreach ($termResult as $result) { $suggestions[] = $result; } } return Response::json($suggestions); } 

Включите пользовательский интерфейс JQuery (и сам JQuery) в свой макет:

 <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> <script src="//code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script> 

Включить тему JQuery UI:

 <link rel="stylesheet" type="text/css" href="//code.jquery.com/ui/1.10.4/themes/redmond/jquery-ui.css"> 

И наконец, добавьте JS для инициализации автозаполнения:

 $(function () { $('input[name="q"]').autocomplete({ source: '/autocomplete', minLength: 2 }); }); 

Это все, что нужно сделать — попробуйте выполнить несколько поисков.

Конфигурация на основе массива

Если вы предпочитаете, вы можете использовать массив для настройки вашего запроса — например:

 $select = array( 'query' => Input::get('q'), 'query_fields' => array('title', 'cast', 'synopsis'), 'start' => 0, 'rows' => 100, 'fields' => array('*', 'id', 'title', 'synopsis', 'cast', 'score'), 'sort' => array('year' => 'asc'), 'filterquery' => array( 'maxprice' => array( 'year' => 'year:[1990 TO 1990]' ), ), 'component' => array( 'facetset' => array( 'facet' => array( array('type' => 'field', 'key' => 'rating', 'field' => 'rating'), ) ), ), ); $query = $this->client->createSelect($select); 

Добавление дополнительных ядер

При запуске SOLR обходит указанный домашний каталог в поисках ядер, которые он идентифицирует, когда находит файл с именем core.propeties . До сих пор мы использовали ядро ​​с именем collection1, и вы увидите, что оно содержит три ключевых элемента:

Файл core.propertes . По своей сути, он просто содержит имя экземпляра.

Каталог conf содержит файлы конфигурации для экземпляра. Как минимум, этот каталог должен содержать schema.xml и файл solrconfig.xml .

Каталог data содержит индексы. Расположение этого каталога может быть изменено, и если он не существует, он будет создан для вас.

Итак, чтобы создать новый экземпляр, выполните следующие действия:

  1. Создайте новый каталог в вашем домашнем каталоге — movies в примере приложения
  2. Создайте каталог conf в этом
  3. Создайте или скопируйте файл schema.xml и solrconfig.xml в каталог conf и настройте их соответствующим образом.
  4. Создайте текстовый файл с именем core.properties в домашнем каталоге со следующим содержимым:

name=instancename

… Где instancename — это имя вашего нового каталога.

Обратите внимание, что конфигурация schema.xml, которая поставляется в каталоге examples содержит ссылки на ряд текстовых файлов — например, stopwords.txt , protwords.txt т. Д. — которые вам также может потребоваться скопировать.

Затем перезапустите SOLR.

Вы также можете добавить новое ядро ​​через административный веб-интерфейс в вашем веб-браузере — нажмите Core Admin с левой стороны, затем Add Core .

Дополнительная конфигурация

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

Файл stopwords.txt — или, более конкретно, файлы для конкретного языка, такие как lang/stopwords_en.txt — содержат слова, которые должны игнорироваться индексатором поиска, такие как «a», «the» и «at». В большинстве случаев вам, вероятно, не потребуется изменять этот файл.

В зависимости от вашего приложения может потребоваться добавить слова в protwords.txt . Этот файл содержит список защищенных слов, которые не являются «основанными», то есть приведены к их базовой форме; например, «спрашивается» становится «спрашивать», «работать» становится «работой». Иногда попытки остановить «исправление» слов, возможно, удаляют ошибочные буквы цифр в конце. Вы можете иметь дело с географическими районами и обнаружить, что «Мэн» связан с «Мэн».

Вы можете указать синонимы — слова с одинаковым значением — в synonyms.txt . Разделяйте синонимы запятыми для каждой строки. Например:

 GB,gib,gigabyte,gigabytes MB,mib,megabyte,megabytes Television, Televisions, TV, TVs 

Вы также можете использовать synoyms.txt для исправления распространенных орфографических ошибок, используя сопоставления синонимов, например:

 assassination => assasination environment => enviroment 

Если вы используете валютные поля, вы можете обновить и следить за currency.xml , в котором указаны некоторые примеры обменных курсов, которые, конечно, очень изменчивы.

Резюме

В этой серии мы рассмотрели реализацию Apache SOLR для поиска и использовали библиотеку PHP Solarium для взаимодействия с ней. Мы установили и настроили SOLR вместе с примером схемы и создали приложение, предназначенное для поиска по ряду фильмов, которое демонстрирует ряд функций SOLR. Мы рассмотрели многогранный поиск, выделив результаты и компонент DisMax. Надеюсь, это даст вам достаточно оснований для адаптации к использованию SOLR для поиска в ваших приложениях.

Для дальнейшего чтения вы можете загрузить справочное руководство по SOLR в формате PDF или ознакомиться с документацией по Solarium .