Обзор работы с индексами в Solr

Данная статья описывает процедуру индексирования в Solr. Индексирование — это процесс добавления нового содержимого в индекс Solr, что делает содержимое доступным для поиска. Также под индексированием стоит понимать изменение и удаление существующего содержимого.

Существует несколько способов доставки данных в Solr для индексирования:

  • Загрузка XML/JSON/CSV-файла в теле запроса HTTP, отправленного на REST-эндпойнт сервера Solr. ADH-компоненты Solr Server поставляются с Post-инструментом, который облегчает загрузку документов через REST-эндпойнт. Этот метод используется в примерах в статье.

  • Использование Solr Admin UI для загрузки документов через веб-интерфейс.

  • Создание клиентского приложения, которое взаимодействует с Solr по HTTP, используя Client API. Например, библиотека SolrJ для приложений на базе JVM.

  • Использование фреймворков, таких как Solr Cell, разработанных для эффективной загрузки данных в Solr.

Независимо от способа доставки данных в Solr существует общая структура для всех данных, загружаемых в индекс. Это должен быть документ, содержащий одно или несколько именованных полей, в каждом из которых хранятся данные. Структура документов определяется файлом схемы (schema file), однако Solr также может принимать документы, которые не соответствуют строгой структуре (schemaless mode). Обычно одно из полей выбирается уникальным, подобно первичному ключу в традиционных базах данных, хотя использование уникального ключа не является обязательным требованием Solr.

Помимо форматов JSON, XML и CSV, Solr может работать с форматами обогащенного текста (rich text format), например HTML, PDF и так далее. В большинстве случаев Solr автоматически определяет тип файла, извлекает данные и не требует указания типа файла вручную.

Больше информации о процедуре индексирования Solr доступно в документации Solr.

Инструмент Post

Каждый компонент Solr Server, развернутый в кластере ADH, поставляется с инструментом Post, который облегчает загрузку документов на сервер Solr. Для работы с инструментом используйте скрипт /usr/lib/solr/bin/post, который доступен на хостах с компонентом Solr Server.

Ниже показан синтаксис запуска скрипта:

$ /usr/lib/solr/post -c <collection_name> [OPTIONS] <file|directory|url|-d ["...",...]>

Поддерживаемые параметры OPTIONS описаны в таблице ниже.

-c <collection_name>

Коллекция Solr для загрузки данных. Необходимо указать либо имя коллекции, либо URL-адрес

-url <URL>

URL REST-эндпойнта сервера Solr. Если значение не указано, URL генерируется автоматически, например http://localhost:<solr_port>/solr/<collection_name>/update. Параметры, указанные в URL, имеют приоритет над параметрами -c, -host и -port

-host <host_name>

Имя хоста или IP-адрес сервера Solr

-port <p>, -p

Номер порта, используемого для подключения

-user <user:pass>, -u <user:pass>

Учетные данные для Basic-аутентификации

-type <content-type>

Значение HTTP-заголовка Content-Type. По умолчанию используется application/xml

-filetypes <type1,…​>

Список типов файлов, принимаемых Solr. По умолчанию Solr принимает файлы следующих типов: xml, json, csv, pdf, doc, docx, ppt, pptx, xls, xlsx, odt, odp, ods, ott, otp, ots, rtf, htm, html, txt, log

-out <yes|no>

Выводит ответ Solr-сервера в консоль

Несколько примеров запуска скрипта /usr/lib/solr/bin/post приведены ниже.

/usr/lib/solr/bin/post -c demo_index_collection transactions.json
/usr/lib/solr/bin/post -c demo_index_collection test-*.xml
/usr/lib/solr/bin/post -c demo_index_collection -out yes test.csv
/usr/lib/solr/bin/post -c demo_index_collection ~/test/solr-docs

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

Далее описаны шаги для индексирования данных в Solr. Данная инструкция показывает, как индексировать простой JSON-документ с помощью инструмента Post.

  1. Подключитесь к хосту ADH, на котором установлен компонент Solr Server.

  2. Создайте тестовую коллекцию Solr с помощью следующей команды:

    $ /usr/lib/solr/bin/solr create -c demo_index_collection -s 2 -rf 2

    Команда создает новую коллекцию demo_index_collection с двумя шардами (shards) и фактором репликации, равным 2. Коллекция создается на основе стандартной конфигурации _default, которая поддерживает бессхемный режим (schemaless mode).

    Вывод:

    Created collection 'demo_index_collection' with 2 shard(s), 2 replica(s) with config-set 'demo_index_collection'
    РЕКОМЕНДАЦИЯ
    Для создания новой коллекции можно также использовать веб-интерфейс Solr.
  3. Создайте тестовый документ в формате JSON, как показано ниже. Можно создать аналогичный документ, используя форматы XML или CSV. Solr автоматически определит тип файла и обработает содержимое документа соответствующим образом.

    {
      "id": 1,
      "txn_id": "1",
      "acc_id": 1001,
      "txn_value": 75.0,
      "txn_date": "2024-01-02",
      "comment": "The first transaction."
    }

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

  4. Используя инструмент Post, загрузите тестовый документ для индексирования с помощью следующей команды:

    $ /usr/lib/solr/bin/post -c demo_index_collection transactions.json

    Запуск скрипта выводит следующее:

    java -classpath /usr/lib/solr/dist/solr-core-8.11.2.jar -Dauto=yes -Dc=demo_index_collection -Ddata=files org.apache.solr.util.SimplePostTool transactions.json
    SimplePostTool version 5.0.0
    Posting files to [base] url http://localhost:8983/solr/demo_index_collection/update...
    Entering auto mode. File endings considered are xml,json,jsonl,csv,pdf,doc,docx,ppt,pptx,xls,xlsx,odt,odp,ods,ott,otp,ots,rtf,htm,html,txt,log
    POSTing file transactions.json (application/json) to [base]/json/docs
    1 files indexed.
    COMMITting Solr index changes to http://localhost:8983/solr/demo_index_collection/update...
    Time spent: 0:00:01.341

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

  1. В Solr Admin UI выберите нужную коллекцию (demo_index_collection в данном примере).

  2. Перейдите на страницу Query.

  3. Кликните Execute Query для выполнения поискового запроса с параметрами по умолчанию. Результаты запроса показаны ниже.

Результаты запроса
Результаты запроса
Результаты запроса
Результаты запроса

Обновление индексированных данных

Чтобы обновить проиндексированный документ, необходимо повторно загрузить измененную версию документа в Solr, убедившись, что уникальный ключ в обновленном документе соответствует документу, который нужно обновить. Если уникальный ключ не указан или указан некорректно, Solr создаст новый документ вместо обновления нужного документа. В стандартной Solr-схеме (схема, принадлежащая конфигурации _default) в качестве уникального ключа используется поле id.

Ниже описаны шаги, необходимые для обновления проиндексированного документа:

  1. Создайте обновленную версию документа, который уже присутствует в индексе Solr. Например, содержимое файла transactions_updated.json:

    {
      "id": 1,
      "txn_id": "1",
      "acc_id": 1001,
      "txn_value": 75.0,
      "txn_date": "2024-01-02",
      "comment": "Updated transaction description."
    }
  2. Загрузите обновленный документ в Solr с помощью инструмента Post:

    $ /usr/lib/solr/bin/post -c demo_index_collection transactions_updated.json

    Вывод:

    java -classpath /usr/lib/solr/dist/solr-core-8.11.2.jar -Dauto=yes -Dc=demo_index_collection -Ddata=files org.apache.solr.util.SimplePostTool transactions_updated.json
    SimplePostTool version 5.0.0
    Posting files to [base] url http://localhost:8983/solr/demo_index_collection/update...
    Entering auto mode. File endings considered are xml,json,jsonl,csv,pdf,doc,docx,ppt,pptx,xls,xlsx,odt,odp,ods,ott,otp,ots,rtf,htm,html,txt,log
    POSTing file transactions_updated.json (application/json) to [base]/json/docs
    1 files indexed.
    COMMITting Solr index changes to http://localhost:8983/solr/demo_index_collection/update...
    Time spent: 0:00:00.307
  3. В Solr Admin UI запросите обновленный документ, указав txn_id:1 в качестве строки запроса (поле q). Такой запрос эквивалентен SQL-запросу SELECT * FROM <collection_name> WHERE txn_id=1;. В ответе содержатся обновленные поля документа, как показано в примере ниже:

    {
      "responseHeader":{
        "zkConnected":true,
        "status":0,
        "QTime":8,
        "params":{
          "q":"txn_id:1",
          "indent":"true",
          "q.op":"OR",
          "_":"1723478346726"}},
      "response":{"numFound":1,"start":0,"maxScore":1.0,"numFoundExact":true,"docs":[
          {
            "id":"1",
            "txn_id":[1],
            "acc_id":[1001],
            "txn_value":[75.0],
            "txn_date":["2024-01-02T00:00:00Z"],
            "comment":["Updated transaction description."],
            "_version_":1807198162248531968}]
      }}

Удаление данных из индекса

Для удаления данных из индекса Solr необходимо отправить delete-команду на REST-эндпойнт обновления, указав уникальный ключ документа либо строку запроса для удаления нескольких документов. Например, чтобы удалить документ с полем id=1, используйте команду:

$ {solr_root}/bin/post -c {test_collection} -d "<delete><id>1</id></delete>"

Для удаления одного или нескольких документов с помощью языка запросов Solr используйте следующий синтаксис:

$ /usr/lib/solr/bin/post -c demo_index_collection -d "<delete><query>txn_id:1</query></delete>"

Команда для удаления всех документов из коллекции выглядит следующим образом:

$ /usr/lib/solr/bin/post -c demo_index_collection -d "<delete><query>*:*</query></delete>"

Поисковые запросы в Solr являются обычными HTTP-запросами, в которых параметры поиска передаются в виде query-параметров URL. Для отправки поискового запроса можно использовать HTTP-клиенты, такие как curl, wget, Postman, или воспользоваться инструментом Post. Пример URL для отправки поискового запроса показан ниже:

http://ka-adh-1.ru-central1.internal:8983/solr/demo_index_collection/select?indent=true&q.op=AND&q=*%3A*

Где ka-adh-1.ru-central1.internal — имя хоста с активным компонентом Solr Server.

Ответ Solr-сервера на такой запрос выглядит следующим образом:

{
    "responseHeader": {
        "zkConnected": true,
        "status": 0,
        "QTime": 6,
        "params": {
            "q": "*:*",
            "indent": "true"
        }
    },
    "response": { (1)
        "numFound": 1,
        "start": 0,
        "maxScore": 1.0,
        "numFoundExact": true,
        "docs": [ (2)
            {
                "id": "1",
                "txn_id": [
                    1
                ],
                "acc_id": [
                    1001
                ],
                "txn_value": [
                    75.0
                ],
                "txn_date": [
                    "2024-01-02T00:00:00Z"
                ],
                "comment": [
                    "Updated transaction description."
                ],
                "_version_": 1807199238892814336
            }
        ]
    }
}
1 Раздел с результатами запроса.
2 Массив найденных документов, которые соответствуют критериям запроса.

Также вы можете использовать Solr Admin UI, который предоставляет удобный интерфейс конструктора запросов.

 
Используя интерфейс конструктора запросов, вы можете указать параметры запроса в отдельных полях и в результате получить готовый URL-адрес запроса, как показано на рисунке ниже.

URL запроса
URL запроса
URL запроса
URL запроса

Парсеры запросов Solr

Когда поисковый запрос поступает в Solr, запрос обрабатывается специальным плагином (request handler), который определяет дальнейшую логику обработки запроса. Затем обработчик запроса активирует парсер запросов (query parser), который интерпретирует параметры полученного запроса. Solr поддерживает несколько парсеров, перечисленных ниже. Перейдя по ссылке, можно получить более подробную информацию об использовании каждого парсера.

  • Standard Query Parser. Парсер запросов по умолчанию. Основным недостатком является неспособность парсера корректно реагировать на синтаксические ошибки.

  • DisMax. Позволяет обрабатывать простые фразы (без сложного синтаксиса) и искать термины по нескольким полям, используя механизм весов (weighting), основанный на значимости каждого поля.

  • Extended DisMax (eDismax). Расширенная версия парсера DisMax, предоставляющая такие возможности, как частичное экранирование, расширенная обработка стоп-слов и так далее.

  • Другие парсеры, например Block Join Query Parser, Boolean Query Parser, Boost Query Parser и так далее.

Примеры поиска

Следующие примеры демонстрируют базовые возможности поиска с использованием стандартного парсера запросов (Standard Query Parser). Подробная информация о параметрах поиска, которые поддерживаются различными парсерами, доступна в документации Solr.

Поиск всех документов с сортировкой

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

Параметры запроса
Параметр Значение

q

*:*

Данная строка запроса по умолчанию эквивалентна SQL-запросу SELECT * FROM <collection_name>

sort

txn_id asc

Пример URL запроса:

http://ka-adh-1.ru-central1.internal:8983/solr/demo_index_collection/select?indent=true&q.op=OR&q=*%3A*&sort=txn_id%20asc

Ответ Solr-сервера:

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":4,
    "params":{
      "q":"*:*",
      "indent":"true",
      "q.op":"OR",
      "sort":"txn_id asc",
      "_":"1723495198651"}},
  "response":{"numFound":3,"start":0,"numFoundExact":true,"docs":[
      {
        "id":"1",
        "txn_id":[1],
        "acc_id":[1001],
        "txn_value":[75.0],
        "txn_date":["2024-01-02T00:00:00Z"],
        "comment":["The first transaction."],
        "_version_":1807214831002976256},
      {
        "id":"3",
        "txn_id":[5],
        "acc_id":[1003],
        "txn_value":[105.0],
        "txn_date":["2024-02-02T00:00:00Z"],
        "comment":["Yet another transaction."],
        "_version_":1807215090454233088},
      {
        "id":"2",
        "txn_id":[256],
        "acc_id":[1002],
        "txn_value":[55.0],
        "txn_date":["2024-02-03T00:00:00Z"],
        "comment":["Another transaction."],
        "_version_":1807214995052691456}]
  }}
Получение значений определенных полей с фильтрацией

 
Следующий пример поискового запроса возвращает только определенные поля (fl=txn_id,acc_id,txn_value,comment) документов, у которых значение txn_date соответствует указанной дате. Кроме того, выполняется фильтрация по полю comment, оставляя в выборке лишь те результаты, в которых содержится строка first.

Параметры запроса
Параметр Значение

q

txn_date:"2024-01-02T00:00:00Z"

fl

txn_id,acc_id,txn_date,comment

fq

comment:\"*first*\"

Пример URL запроса:

http://ka-adh-1.ru-central1.internal:8983/solr/demo_index_collection/select?fl=txn_id%2Cacc_id%2Ctxn_value%2Ccomment&fq=comment%3A%22*first1*%22&indent=true&q.op=OR&q=txn_date%3A%222024-01-02T00%3A00%3A00Z%22

Ответ Solr-сервера:

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":5,
    "params":{
      "q":"txn_date:\"2024-01-02T00:00:00Z\"",
      "indent":"true",
      "fl":"txn_id,acc_id,txn_value,comment",
      "q.op":"OR",
      "fq":"comment:\"*first*\"",
      "_":"1723492286745"}},
  "response":{"numFound":1,"start":0,"maxScore":1.0,"numFoundExact":true,"docs":[
      {
        "txn_id":[1],
        "acc_id":[1001],
        "txn_value":[75.0],
        "comment":["The first transaction."]}]
  }}
Комбинация условий поиска

 
Используя булевы операторы, можно создавать сложную логику запросов и комбинировать несколько условий поиска. Например, следующий запрос выполняет поиск документов, у которых в поле comment содержится строка transaction, а поле txn_id равно 1.

Параметры запроса
Параметр Значение

q

comment:transaction AND txn_id:1

Пример URL запроса:

http://ka-adh-1.ru-central1.internal:8983/solr/demo_index_collection/select?indent=true&q.op=OR&q=comment%3Atransaction%20AND%20txn_id%3A1

Ответ Solr-сервера:

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":4,
    "params":{
      "q":"comment:transaction AND txn_id:1",
      "indent":"true",
      "q.op":"OR",
      "_":"1723492286745"}},
  "response":{"numFound":1,"start":0,"maxScore":1.1307646,"numFoundExact":true,"docs":[
      {
        "id":"1",
        "txn_id":[1],
        "acc_id":[1001],
        "txn_value":[75.0],
        "txn_date":["2024-01-02T00:00:00Z"],
        "comment":["The first transaction."],
        "_version_":1807214831002976256}]
  }}
Поиск по диапазону

 
Следующий запрос возвращает документы, у которых значение поля txn_value попадает в диапазон 100-200.

Параметры запроса
Параметр Значение

q

txn_value:[100 TO 200]

Пример URL запроса:

http://ka-adh-1.ru-central1.internal:8983/solr/demo_index_collection/select?fl=txn_id%2Ctxn_value%2Cacc_id&indent=true&q.op=AND&q=txn_value%3A%5B100%20TO%20200%5D

Ответ Solr-сервера:

{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":8,
    "params":{
      "q":"txn_value:[100 TO 200]",
      "indent":"true",
      "fl":"txn_id,txn_value,acc_id",
      "q.op":"AND",
      "_":"1723539053709"}},
  "response":{"numFound":1,"start":0,"maxScore":1.0,"numFoundExact":true,"docs":[
      {
        "txn_id":[5],
        "acc_id":[1003],
        "txn_value":[105.0]}]
  }}
Размер и формат ответа Solr-cервера

 
Следующий запрос возвращает первые три документа, которые соответствуют критериям поиска. Также в запросе указано, что сервер Solr должен вернуть ответ в формате XML.

Параметры запроса
Параметр Значение

q

*:*

rows

3

wt

xml

Пример URL запроса:

http://ka-adh-1.ru-central1.internal:8983/solr/demo_index_collection/select?indent=true&q.op=OR&q=*%3A*&rows=3&start=0&wt=xml

Ответ Solr-сервера:

<?xml version="1.0" encoding="UTF-8"?>
<response>

<lst name="responseHeader">
  <bool name="zkConnected">true</bool>
  <int name="status">0</int>
  <int name="QTime">4</int>
  <lst name="params">
    <str name="q">*:*</str>
    <str name="indent">true</str>
    <str name="start">0</str>
    <str name="q.op">OR</str>
    <str name="rows">3</str>
    <str name="wt">xml</str>
    <str name="_">1723492286745</str>
  </lst>
</lst>
<result name="response" numFound="3" start="0" maxScore="1.0" numFoundExact="true">
  <doc>
    <str name="id">2</str>
    <arr name="txn_id">
      <long>256</long>
    </arr>
    <arr name="acc_id">
      <long>1002</long>
    </arr>
    <arr name="txn_value">
      <double>55.0</double>
    </arr>
    <arr name="txn_date">
      <date>2024-02-03T00:00:00Z</date>
    </arr>
    <arr name="comment">
      <str>Another transaction.</str>
    </arr>
    <long name="_version_">1807214995052691456</long></doc>
  <doc>
    <str name="id">3</str>
    <arr name="txn_id">
      <long>5</long>
    </arr>
    <arr name="acc_id">
      <long>1003</long>
    </arr>
    <arr name="txn_value">
      <double>105.0</double>
    </arr>
    <arr name="txn_date">
      <date>2024-02-02T00:00:00Z</date>
    </arr>
    <arr name="comment">
      <str>Yet another transaction.</str>
    </arr>
    <long name="_version_">1807215090454233088</long></doc>
  <doc>
    <str name="id">1</str>
    <arr name="txn_id">
      <long>1</long>
    </arr>
    <arr name="acc_id">
      <long>1001</long>
    </arr>
    <arr name="txn_value">
      <double>75.0</double>
    </arr>
    <arr name="txn_date">
      <date>2024-01-02T00:00:00Z</date>
    </arr>
    <arr name="comment">
      <str>The first transaction.</str>
    </arr>
    <long name="_version_">1807214831002976256</long></doc>
</result>
</response>
Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней