Это четвертая и последняя часть серии об использовании реализации поиска 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
содержит индексы. Расположение этого каталога может быть изменено, и если он не существует, он будет создан для вас.
Итак, чтобы создать новый экземпляр, выполните следующие действия:
- Создайте новый каталог в вашем домашнем каталоге —
movies
в примере приложения - Создайте каталог
conf
в этом - Создайте или скопируйте файл
schema.xml
иsolrconfig.xml
в каталогconf
и настройте их соответствующим образом. - Создайте текстовый файл с именем
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 .