Apache SOLR — это поисковая платформа уровня предприятия, основанная на Apache Lucene. Он обеспечивает мощный полнотекстовый поиск наряду с расширенными функциями, такими как граненый поиск, выделение результатов и геопространственный поиск. Это чрезвычайно масштабируемый и отказоустойчивый.
Известные веб-сайты, использующие SOLR для обеспечения своих функций поиска, включают digg, Netflix, Instagram и Whitehouse.gov ( источник ).
Хотя SOLR написан на Java, он доступен через HTTP, что позволяет интегрироваться с любым языком программирования, который вы предпочитаете. Если вы используете PHP, то Solarium Project делает интеграцию еще проще, обеспечивая уровень абстракции над базовыми запросами, что позволяет вам использовать SOLR, как если бы это была собственная реализация, работающая в вашем приложении.
В этой серии я собираюсь представить одновременно SOLR и Solarium. Мы начнем с установки и настройки SOLR и создания поискового индекса. Затем мы рассмотрим, как индексировать документы. Далее мы реализуем базовый поиск, а затем расширяем его некоторыми более продвинутыми функциями, такими как граненый поиск, выделение результатов и предложения.
По мере продвижения мы собираемся создать простое приложение для поиска в коллекции фильмов. Вы можете получить исходный код здесь или посмотреть онлайн-демонстрацию здесь .
Основные понятия и операции
Прежде чем мы углубимся в реализацию, стоит взглянуть на несколько основных концепций и общее представление о том, что произойдет.
SOLR — это Java-приложение, которое работает как веб-сервис, обычно в контейнере сервлетов, таком как Tomcat, Glassfish или JBoss. Вы можете манипулировать и запрашивать его по HTTP, используя XML, JSON, CSV или двоичный формат — так что вы можете использовать любой язык программирования для своего приложения. Однако библиотека Solarium обеспечивает уровень абстракции, позволяя вам вызывать методы, как если бы SOLR была нативной реализацией. Для целей данного руководства мы будем запускать SOLR на той же машине, что и наше приложение, но на практике он может быть расположен на отдельном сервере.
SOLR создает поисковый индекс документов . Часто это отражает то, что мы можем считать документом в реальной жизни; статья, сообщение в блоге или даже полная книга. Однако документ может также представлять любой объект, применимый к вашему приложению — продукт, место, событие — или в нашем примере приложения — фильм.
По своей сути SOLR позволяет выполнять полнотекстовый поиск по документам. Думаю, поисковые системы; Вы обычно будете искать ключевое слово, фразу или полный заголовок. Вы можете продвинуться так далеко с предложением SQL LIKE
; вот где приходит полнотекстовый поиск.
Вы также можете прикрепить дополнительную информацию к индексируемому поисковому документу, который не обязательно будет обнаружен текстовым поиском; например, вы можете указать цену товара, количество комнат в собственности или дату добавления предмета в базу данных.
Грани являются одной из самых полезных функций SOLR. Вы, вероятно, видели граненый поиск, если вы когда-либо делали покупки в Интернете; Фасеты позволяют «детализировать» результаты поиска, применяя «фильтры». Например, выполнив поиск в книжном интернет-магазине, вы можете использовать фильтры, чтобы ограничить результаты для этих книг конкретным автором, в определенном жанре или в определенном формате.
Экземпляр SOLR работает с одним или несколькими ядрами. Ядро — это набор конфигурации и индексов, каждый со своей схемой. Как правило, один экземпляр является специфическим для конкретного приложения. Поскольку разные типы контента могут иметь очень разные структуры и информацию — например, учитывать разницу между продуктом, статьей и пользователем — приложение часто имеет несколько ядер в экземпляре SOLR.
Установка SOLR
Я собираюсь предоставить инструкции о том, как настроить SOLR на Mac; для других операционных систем обратитесь к документации — или же вы можете загрузить Blaze , устройство с предустановленной SOLR.
Самый простой способ установить SOLR на Mac — это использовать Homebrew :
brew update brew install solr
Это установит программное обеспечение в каталог, такой как /usr/local/Cellar/solr/4.5.0
, в зависимости от того, какую версию программного обеспечения вы используете.
Чтобы запустить сервер, используя предоставленный архив Java (JAR):
cd /usr/local/Cellar/solr/4.5.0/libeexec/example java -jar start.jar
Чтобы убедиться, что установка прошла успешно, попробуйте получить доступ к интерфейсу администратора в вашем веб-браузере:
http://localhost:8983/solr/
Если вы видите панель администратора с логотипом Apache SOLR в левом верхнем углу, сервер запущен и работает.
СОВЕТ: чтобы остановить SOLR — что вам нужно будет делать всякий раз, когда вы меняете конфигурацию, как мы собираемся сделать в ближайшее время — просто нажмите CTRL + C
(Инструкции для Linux: http://www.lullabot.com/blog/article/install-solr-use-drupal )
Настройка схемы
Вероятно, самый простой способ начать работу с SOLR — это скопировать каталог по умолчанию, а затем настроить его.
Скопируйте каталог libexec/example
из libexec/example
; здесь мы создаем новое ядро SOLR под названием «фильмы»:
cd /usr/local/Cellar/solr/4.5.0/libeexec/example cp -R solr movies
Мы рассмотрим файлы конфигурации, movies\solr.xml
и movies\collection1\conf\solrconfig.xml
позже. На данный момент нас действительно интересует схема, которая определяет поля в документах, которые мы индексируем, а также то, как они обрабатываются.
Файл, который определяет это, — movies\collection1\conf\schema.xml
.
Если вы откроете только что скопированный файл, вы увидите, что он не только содержит некоторые полезные значения по умолчанию, но также подробно прокомментирован, чтобы помочь вам понять, как его настроить.
Файл конфигурации схемы отвечает за два основных аспекта; поля и типы . Типы — это просто типы данных, и они скрывают имена типов — такие как целые числа, даты и строки — с базовыми классами Java, используемыми в реализации. Например: solr.TrieIntField
, solr.TrieDateField
и solr.TextField
. Конфигурация типов также определяет поведение токенизаторов, анализаторов и фильтров.
Вот несколько примеров основных типов:
<fieldType name = "string" class = "solr.StrField" sortMissingLast = "true" omitNorms = "true" />
<fieldType name = "long" class = "solr.TrieLongField" precisionStep = "0" positionIncrementGap = "0" />
<fieldType name = "int" class = "solr.TrieIntField" precisionStep = "0" positionIncrementGap = "0" />
<fieldType name = "tdouble" class = "solr.TrieDoubleField" precisionStep = "8" omitNorms = "true" positionIncrementGap = "0" />
string
тип требует более пристального взгляда, потому что там есть недочет. Когда вы используете поле в качестве строки, любые данные сохраняются именно в том виде, в котором вы их вводите. Кроме того, чтобы запрос соответствовал ему, он должен быть идентичным. Например, предположим, что у вас есть заголовок статьи в виде строки и вставлен документ под названием «Введение в SOLR». В любой правильной реализации поиска вы ожидаете найти статью с запросом типа «Введение в SOLR», не говоря уже о «введении в Solr». Чтобы обойти это, если вам не нужно это поведение с точным соответствием, которое на самом деле полезно в некоторых случаях, таких как фасетный поиск, вы можете использовать комбинацию токенизаторов и фильтров.
Токенизаторы разбивают текст на куски — обычно это отдельные слова. Фильтры каким-то образом преобразуют текст. Чтобы проиллюстрировать это, давайте посмотрим на разумное значение по умолчанию для текста:
<fieldType name = "text_general" class = "solr.TextField" positionIncrementGap = "100" >
<analyzer type = "index" >
<tokenizer class = "solr.StandardTokenizerFactory" />
<filter class = "solr.StopFilterFactory" ignoreCase = "true" words = "stopwords.txt" />
<filter class = "solr.LowerCaseFilterFactory" />
</analyzer>
<analyzer type = "query" >
<tokenizer class = "solr.StandardTokenizerFactory" />
<filter class = "solr.StopFilterFactory" ignoreCase = "true" words = "stopwords.txt" />
<filter class = "solr.SynonymFilterFactory" synonyms = "synonyms.txt" ignoreCase = "true" expand = "true" />
<filter class = "solr.LowerCaseFilterFactory" />
</analyzer>
</fieldType>
Во-первых, вы заметите, что мы определяем поведение во время индексации — другими словами, как преобразуются данные при добавлении документа — и во время запроса. В этом примере LowerCaseFilterFactory
преобразует данные в нижний регистр как при индексировании, так и при запросе, поэтому использование заглавных букв становится неактуальным, и мы можем сделать сравнение по LowerCaseFilterFactory
похож на что». В нашем примере «введение» будет соответствовать «Введение», а «SOLR» будет соответствовать «Solr».
StopFilterFactory
используется для удаления стоп-слов, которые являются общими словами, которые исключаются либо потому, что они не имеют отношения к поиску, либо для эффективности — такие слова, как «a», «the», «and», «etc». Здесь есть хороший, исчерпывающий список стоп-слов. В приведенном выше коде стоп-слова настраиваются в отдельном текстовом файле.
Раздел fields
используется для определения доступных полей, их типов и дополнительной информации, например, имеют ли они множественные значения, должны ли они быть проиндексированы и т. Д.
Мы не собираемся пытаться модифицировать или расширять определения типов — это выходит за рамки данного руководства — но вместо этого мы рассмотрим определения полей.
Вообще говоря, существует два подхода к определению структуры ваших документов. Первый заключается в явном определении всех возможных полей. Второе — использовать динамические поля, которые позволяют вам добавлять поля на лету, если вы придерживаетесь определенных соглашений об именах. Например, с учетом следующего определения динамического поля:
<dynamicField name="*_s" type="string" indexed="true" stored="true" />
… Вы можете добавить, скажем, одно свойство значения с именем author_s
в документ, и оно будет сохранено в виде строки, без предварительной настройки. (Примечание: части «author» и «s» полностью разделены, поэтому не читайте их как множественное число «авторов».) Следующее определяет многозначное строковое поле:
<dynamicField name="*_ss" type="string" indexed="true" stored="true" multiValued="true"/>
… Так, например, вы можете добавить категории, используя categories_ss
.
Если вы попытаетесь добавить документ в поисковый индекс, который содержит свойства, которые не были явно определены — или, если вы используете динамические свойства и не придерживаетесь этих соглашений — тогда SOLR выдаст ошибку. Чтобы изменить это поведение, найдите и раскомментируйте (или добавьте) следующую строку:
<dynamicField name="*" type="ignored" multiValued="true" />
Эта строка указывает, что свойства, которые ранее не были определены, должны игнорироваться, а не генерировать ошибку. Однако, поскольку они игнорируются, имейте в виду, что они не будут ни проиндексированы, ни сохранены — поэтому они не окажут никакого влияния на любые поиски, которые вы можете выполнить.
В целях этого урока мы собираемся явно определить поля, которые мы хотим.
<field name = "id" type = "string" indexed = "true" stored = "true" required = "true" multiValued = "false" />
<field name = "title" type = "text_general" indexed = "true" stored = "true" />
<field name = "synopsis" type = "text_general" indexed = "true" stored = "true" omitNorms = "true" />
<field name = "rating" type = "string" indexed = "true" stored = "true" />
<field name = "cast" type = "text_general" indexed = "true" stored = "true" multiValued = "true" />
<field name = "year" type = "int" indexed = "true" stored = "true" />
<field name = "runtime" type = "int" indexed = "true" stored = "true" />
SOLR требует следующую строку:
<field name="_version_" type="long" indexed="true" stored="true"/>
Следующее поле не используется; однако, поскольку в solrconfig.xml
есть несколько ссылок на него, solrconfig.xml
его на некоторое время:
<field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>
Нам также необходимо указать, какое поле является уникальным идентификатором — например, первичный ключ в терминологии SQL — следующим образом:
<uniqueKey>id</uniqueKey>
Теперь нам нужно указать SOLR, какую конфигурацию использовать. Остановите сервер, если он в данный момент работает (CTRL + C), и на этот раз запустите его с флагом Dsolr.solr.home
:
cd /usr/local/Cellar/solr/4.5.0/libeexec/example java -jar start.jar -Dsolr.solr.home=movies
Резюме
Вот и все для первой части, где мы начали смотреть на SOLR и Solarium. У нас установлен SOLR и настроена схема. В следующей части мы настроим наше приложение вместе с Solarium и проиндексируем некоторые данные.