Elasticsearch нумерация страниц лучший подход - PullRequest
0 голосов
/ 27 февраля 2020

Мы разработали решение для хранения файлов, которое использует elasti c search для хранения метаданных о файлах, используя клиентский уровень java API.

В настоящее время мы разбиваем на страницы нумерацию с использованием параметров from и size ». Клиент звонит нам с указанием размера и может также указать номер страницы, мы используем номер страницы для вычисления смещения или «от».

Им также разрешается сортировать по любому полю, которое можно назвать из строк датам, целым числам и т. д. c, но мы по умолчанию назначаем дату создания

. От и размер вызывает проблемы с глубоким разбиением на страницы, например (решение 1)

1. /rest/metadata/search*

  1. numberOfHitsPerPage = 5000
  2. from(0),size(5000)

2. /rest/metadata/search?pageNumber=2

  1. numberOfHitsPerPage=5000
  2. from(5000),size(5000)

3. /rest/metadata/search?pageNumber=3

  1. from(10000),size(5000)
  2. From + size = 15,000, which is over the index.max_result_window of 10,000 and will fail.

Я изучил функцию searchAfter и реализовал ее, поэтому в ответе мы возвращаем последнее значение индекса «sort», которое клиент может использовать при последующих вызовах, чтобы избежать вышеуказанной проблемы. Пример. (Решение 2)

1. /rest/metadata/search

  1. numberOfHitsPerPage = 5000
  2. We return the 5000 hits but also include the sort value of the last hit.

2. /rest/metadata/search?lastIndexValue=1581418484000

  1. numberOfHitsPerPage=5000
  2. Under the hood we then use search_after to search from 1581418484000, return the next 5000 hits and the new last index.

3. /rest/metadata/search? lastIndexValue=1581418484011

  1. numberOfHitsPerPage=5000
  2. Under the hood we then use search_after to search from 1581418484011, return the next 5000 hits and return the new last index.
  3. There is no exception here because the filter is applied on the search request itself @ 5000 a time.

В некоторых случаях это работает нормально, но дает нам странные результаты также потому, что, как я упоминал выше, мы разрешаем сортировку по любому полю, поэтому, например, у нас хранится 100 файлов, все с «расширением» поле установлено в txt, а 100 в pdf, поэтому пользователь делает один вызов с размером, равным 10, и хочет отсортировать по «расширению», мы возвращаем их вместе с последним индексом «sort», который является «txt», «txt» затем используется в последующих вызовах для поля searchAfter, но это не дает никаких результатов.

Таким образом, похоже, что searchAfter хорошо работает только с такими полями, как даты и т. д. c.

Я был думая потенциально, мы могли бы хранить значение lastSorted (индекс) внутри, поэтому go вернемся к решению 1, но если из + size> 10000 использовать последнее значение сортировки, и оно скрыто для пользователя клиента. Единственная проблема, с которой я сталкиваюсь, заключается в том, где мы можем хранить последнее значение сортировки, а последнее значение сортировки должно быть уникальным для каждого поиска. Я не хочу, чтобы огромная БД заполнялась всеми значениями сортировки исключительно для этого.

Мысли?

Спасибо,

1 Ответ

0 голосов
/ 28 февраля 2020

Как вы правильно заметили, техника from и size не позволяет выполнять глубокую нумерацию страниц. С search_after вы можете искать настолько глубоко, насколько хотите.

Но search_after не позволяет вам случайным образом «прыгать», но вы можете получать попадания последовательно. Для каждого последующего запроса необходимо указать значения параметров сортировки последнего попадания предыдущего запроса. Значения сортировки должны быть уникальными. Поскольку сортировка только по одному значению (например, _score или суффикс), скорее всего, не уникальна, вам нужно указать второй критерий сортировки (в идеале, уникальное значение), чтобы последний удар предыдущего запроса был однозначно идентифицирован.

Для этого можно использовать поле _id, но это будет не очень эффективно, поскольку Elasticsearch не записывает структуру данных do c -значения для поля _id. Поэтому используйте для этой цели любое другое уникальное поле типа keyword (например, uri). Если у вас нет такого поля с уникальным значением для каждого документа, просто скопируйте значение поля _id в новое поле типа keyword. Вы можете сделать это, например, в конвейере загрузки.

...