Рубрики
Без рубрики

Полнотекстовый поиск с помощью Solr

Узнайте, как использовать возможности и функции поисковой системы Solr, такие как создание различных запросов, фасетирование поиска, выделение и предложение терминов.

Автор оригинала: baeldung.

1. Обзор

В этой статье мы рассмотрим фундаментальную концепцию в Apache Solr поисковой системе – полнотекстовый поиск.

Apache Solr-это платформа с открытым исходным кодом, предназначенная для работы с миллионами документов. Мы рассмотрим основные возможности ит с примерами использования библиотеки Java – SolrJ .

2. Конфигурация Maven

Учитывая тот факт, что Solr является открытым исходным кодом – мы можем просто загрузить двоичный файл и запустить сервер отдельно от нашего приложения.

Для связи с сервером мы определим зависимость Maven для клиента SolrJ:


    org.apache.solr
    solr-solrj
    6.4.2

Вы можете найти последнюю зависимость здесь .

3. Индексирование данных

Для индексации и поиска данных нам нужно создать core ; мы создадим один с именем item для индексации наших данных.

Прежде чем мы это сделаем, нам нужно, чтобы данные были проиндексированы на сервере, чтобы они стали доступными для поиска.

Существует множество различных способов индексирования данных. Мы можем использовать обработчики импорта данных для импорта данных непосредственно из реляционных баз данных, загрузки данных с помощью ячейки Solr с помощью Apache Tika или загрузки данных XML/XSLT, JSON и CSV с помощью обработчиков индексов.

3.1. Индексирование документа Solr

Мы можем индексировать данные в core , создав SolrInputDocument . Сначала нам нужно заполнить документ нашими данными, а затем только вызвать API Solrj для индексации документа:

SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", id);
doc.addField("description", description);
doc.addField("category", category);
doc.addField("price", price);
solrClient.add(doc);
solrClient.commit();

Обратите внимание, что id , естественно, должен быть уникальным для разных элементов . Наличие id уже проиндексированного документа приведет к обновлению этого документа.

3.2. Индексация Бобов

SolrJ предоставляет API для индексирования компонентов Java. Чтобы индексировать боб, нам нужно аннотировать его с помощью @Field аннотации:

public class Item {

    @Field
    private String id;

    @Field
    private String description;

    @Field
    private String category;

    @Field
    private float price;
}

Как только у нас есть боб, индексация становится простой:

solrClient.addBean(item); 
solrClient.commit();

4. Запросы Solr

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

4.1. Основные запросы

Сервер предоставляет API для операций поиска. Мы можем либо вызвать /select , либо /query обработчики запросов.

Давайте сделаем простой поиск:

SolrQuery query = new SolrQuery();
query.setQuery("brand1");
query.setStart(0);
query.setRows(10);

QueryResponse response = solrClient.query(query);
List items = response.getBeans(Item.class);

SolrJ будет внутренне использовать основной параметр запроса q в своем запросе к серверу. Количество возвращаемых записей будет равно 10, проиндексированных с нуля, когда start и строки не указаны.

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

Давайте рассмотрим другой пример. Мы хотим найти любое слово , содержащее “r и” , которое начинается с любого количества символов и заканчивается только одним символом. Мы можем использовать подстановочные знаки * и ? в нашем запросе:

query.setQuery("*rand?");

Запросы Solr также поддерживают логические операторы, как в SQL:

query.setQuery("brand1 AND (Washing OR Refrigerator)");

Все логические операторы должны быть во всех заглавных буквах; те, которые поддерживаются анализатором запросов, – это И , ИЛИ, НЕ , + и – .

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

query.setQuery("description:Brand* AND category:*Washing*");

4.2. Запросы фраз

До этого момента наш код искал ключевые слова в индексированных полях. Мы также можем выполнять поиск по фразам в индексированных полях:

query.setQuery("Washing Machine");

Когда у нас есть фраза типа ” Стиральная машина “, стандартный анализатор запросов Solr анализирует ее на ” Стиральная машина ИЛИ машина “. Для поиска целой фразы мы можем добавить выражение только в двойные кавычки:

query.setQuery("\"Washing Machine\"");

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

query.setQuery("\"Washing equipment\"~2");

4.3. Запросы диапазона

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

Допустим, мы хотим найти товары, цена которых колеблется от 100 до 300:

query.setQuery("price:[100 TO 300]");

В приведенном выше запросе будут найдены все элементы, цена которых составляет от 100 до 300 включительно. Мы можем использовать ” } ” и ” { ” для исключения конечных точек:

query.setQuery("price:{100 TO 300]");

4.4. Фильтрация запросов

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

SolrQuery query = new SolrQuery();
query.setQuery("price:[100 TO 300]");
query.addFilterQuery("description:Brand1","category:Home Appliances");

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

5. Фасетный поиск

Фасетирование помогает упорядочить результаты поиска по группам. Мы можем фасетировать поля, запросы или диапазоны.

5.1. Огранка полей

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

query.addFacetField("category");

QueryResponse response = solrClient.query(query);
List facetResults = response.getFacetField("category").getValues();

Результаты фасета будут содержать подсчеты каждой категории в результатах.

5.2. Фасетирование запросов

Фасетирование запросов очень полезно, когда мы хотим вернуть количество подзапросов:

query.addFacetQuery("Washing OR Refrigerator");
query.addFacetQuery("Brand2");

QueryResponse response = solrClient.query(query);
Map facetQueryMap = response.getFacetQuery();

В результате карта фасетных запросов будет содержать количество фасетных запросов.

5.3. Огранка диапазона

Фасетирование диапазона используется для получения количества диапазонов в результатах поиска. Следующий запрос вернет количество ценовых диапазонов между 100 и 251, разделенных на 25:

query.addNumericRangeFacet("price", 100, 275, 25);

QueryResponse response = solrClient.query(query);
List rangeFacets =  response.getFacetRanges().get(0).getCounts();

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

6. Подсветка хита

Мы можем захотеть, чтобы ключевые слова в вашем поисковом запросе были выделены в результатах. Это будет очень полезно, чтобы получить лучшее представление о результатах. Давайте проиндексируем некоторые документы и определим ключевые слова, которые будут выделены:

itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing equipments", 250f);

SolrQuery query = new SolrQuery();
query.setQuery("Appliances");
query.setHighlight(true);
query.addHighlightField("category");
QueryResponse response = solrClient.query(query);

Map>> hitHighlightedMap = response.getHighlighting();
Map> highlightedFieldMap = hitHighlightedMap.get("hm0001");
List highlightedList = highlightedFieldMap.get("category");
String highLightedText = highlightedList.get(0);

Мы получим Выделенный текст как “Главная Бытовая техника” . Обратите внимание, что ключевое слово поиска Appliances помечено тегом . Тег выделения по умолчанию , используемый Solr, – это , но мы можем изменить это, установив теги pre и post :

query.setHighlightSimplePre("");
query.setHighlightSimplePost("");

7. Поиск предложений

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

7.1. Проверка орфографии

Стандартный обработчик поиска не включает компонент проверки орфографии; он должен быть настроен вручную. Есть три способа сделать это. Вы можете найти подробную информацию о конфигурации на официальной странице wiki|/. В нашем примере мы будем использовать IndexBasedSpellChecker , который использует индексированные данные для проверки орфографии ключевых слов.

Давайте поищем ключевое слово с орфографической ошибкой:

query.setQuery("hme");
query.set("spellcheck", "on");
QueryResponse response = solrClient.query(query);

SpellCheckResponse spellCheckResponse = response.getSpellCheckResponse();
Suggestion suggestion = spellCheckResponse.getSuggestions().get(0);
List alternatives = suggestion.getAlternatives();
String alternative = alternatives.get(0);

Ожидаемая альтернатива для вашего ключевого слова “home” должна быть “home” , поскольку ваш индекс содержит термин “home”. Обратите внимание, что проверка орфографии должна быть активирована перед выполнением поиска.

7.2. Автоматическое предложение Условий

Возможно, нам захочется получить предложения по неполным ключевым словам, чтобы помочь в поиске. Компонент предложения Solr должен быть настроен вручную. Вы можете найти подробную информацию о конфигурации на его официальной странице wiki|/.

Мы настроили обработчик запросов с именем /suggest для обработки предложений. Давайте получим предложения по ключевому слову “Home” :

SolrQuery query = new SolrQuery();
query.setRequestHandler("/suggest");
query.set("suggest", "true");
query.set("suggest.build", "true");
query.set("suggest.dictionary", "mySuggester");
query.set("suggest.q", "Hom");
QueryResponse response = solrClient.query(query);
        
SuggesterResponse suggesterResponse = response.getSuggesterResponse();
Map> suggestedTerms = suggesterResponse.getSuggestedTerms();
List suggestions = suggestedTerms.get("mySuggester");

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

8. Заключение

Эта статья представляет собой краткое введение в возможности и возможности поисковой системы Solr.

Мы затронули многие функции, но это, конечно, только царапина на поверхности того, что мы можем сделать с помощью продвинутого и зрелого поискового сервера, такого как Solr.

Примеры, используемые здесь, доступны, как всегда, на GitHub .