Elasticsearch 2.1: окно результатов слишком велико (index.max_result_window)

86

Мы получаем информацию из Elasticsearch 2.1 и позволяем пользователю просматривать результаты. Когда пользователь запрашивает большой номер страницы, мы получаем следующее сообщение об ошибке:

Окно результатов слишком велико, размер от + должен быть меньше или равен: [10000], но был [10020]. См. Api прокрутки для более эффективного способа запроса больших наборов данных. Это ограничение можно установить, изменив параметр уровня индекса [index.max_result_window].

В эластичном документе говорится, что это связано с высоким потреблением памяти и использованием прокрутки api:

Значения выше, чем могут потреблять значительные фрагменты памяти кучи на поиск и на сегмент, выполняющий поиск. Безопаснее всего оставить это значение, так как это использование api прокрутки для любой глубокой прокрутки https://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

Дело в том, что я не хочу получать большие наборы данных. Я хочу получить только фрагмент из набора данных, который находится очень высоко в наборе результатов. Также в документе прокрутки говорится:

Прокрутка не предназначена для запросов пользователей в реальном времени https://www.elastic.co/guide/en/elasticsearch/reference/2.2/search-request-scroll.html

Это оставляет мне несколько вопросов:

1) Будет ли потребление памяти действительно ниже (если да, то почему), если я использую api прокрутки для прокрутки до результата 10020 (и игнорирую все, что ниже 10000) вместо выполнения «обычного» поискового запроса для результата 10000-10020?

2) Мне не кажется, что API прокрутки - вариант для меня, но мне нужно увеличить index.max_result_window. У кого-нибудь есть опыт с этим?

3) Есть ли другие варианты решения моей проблемы?

Рональд
источник

Ответы:

79

Если вам нужна глубокая разбивка на страницы, одно из возможных решений - увеличить значение max_result_window. Вы можете использовать curlдля этого из командной строки оболочки:

curl -XPUT "http://localhost:9200/my_index/_settings" -H 'Content-Type: application/json' -d '{ "index" : { "max_result_window" : 500000 } }'

Я не заметил увеличения использования памяти, для значений ~ 100k.

Андрей Морозов
источник
У меня такая же ошибка. 'Result window is too large, from + size must be less than or equal to: [10000] but was [47190]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level parameter.')Он сказал, что у него 4719 страниц (каждая страница 10 результатов). и я думаю, что ваше предложение работает.
dotslash
1
Это хорошее решение для небольшого количества документов менее чем 500000
Эззат
2
Я использую ES v2.2.0, и мне пришлось изменить полезную нагрузку, чтобы { "max_result_window" : 500000 }это работало. Таким образом, команда локон стал -curl -XPUT "http://localhost:9200/my_index/_settings" -d '{ "max_result_window" : 500000 }'
Parin Porecha
3
для тех, кто получает ошибку заголовка с помощью этой команды для более новой версии elasticsearch, вам также необходимо передать заголовок, curl -XPUT " localhost: 9200 / my_index / _settings " -H "Content-Type: application / json" -d '{ "index": {"max_result_window": 50000}} '
Сатис,
32

Правильным решением будет использование прокрутки.
Однако, если вы хотите расширить searchвозвращаемые результаты за пределы 10 000 результатов, вы можете легко сделать это с помощью Kibana:

Перейдите по Dev Toolsссылке и просто опубликуйте следующее в свой индекс (your_index_name), указав, каким будет новое окно максимального результата

введите описание изображения здесь

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

Если все пойдет хорошо, вы должны увидеть следующий успешный ответ:

{
  "acknowledged": true
}
Гай Дубровски
источник
1
Я попытался сделать это в коде elasticsearch (put_settings и т. Д.) И обнаружил много ошибок. Это сэкономит мне часы! Спасибо!
cpres
24

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

https://www.elastic.co/guide/en/elasticsearch/guide/current/pagination.html https://www.elastic.co/guide/en/elasticsearch/guide/current/_fetch_phase.html

В зависимости от размера ваших документов, количества сегментов и оборудования, которое вы используете, разбиение на страницы от 10 000 до 50 000 результатов (от 1 000 до 5 000 страниц) должно быть вполне выполнимым. Но с достаточно большими значениями from процесс сортировки может стать действительно очень тяжелым, поскольку он требует огромных ресурсов процессора, памяти и полосы пропускания. По этой причине мы настоятельно не рекомендуем использовать глубокую подкачку.

Рональд
источник
1
Итак, здесь мы должны отказаться от глубокой разбивки на страницы, верно? По сути, нет смысла перелистывать 4000 страниц для одного зрителя. Допустим, поиск Google, вряд ли мы прокручиваем страницу 8 или 9, чтобы проверить результаты. Обычно мы заботимся только о 3-5 верхних страницах, которые предоставляет нам Google.
dotslash
2
Можем ли мы использовать API прокрутки, если нам нужна глубокая разбивка на страницы?
Abhi.G
3
Но когда мы включаем функцию сортировки, скажем, на сайте электронной коммерции. когда пользователь хочет увидеть товары с самой высокой ценой. Результат будет другим, когда мы сортируем по самой высокой цене по сравнению с тем, когда мы сортируем по самой низкой странице, но переходим к последней странице, верно? поскольку мы ограничиваем количество результатов, к которым можно получить доступ. любая работа для этого?
MR Murazza
3

Используйте Scroll API, чтобы получить более 10000 результатов.

Пример прокрутки в ElasticSearch NEST API

Я использовал это так:

private static Customer[] GetCustomers(IElasticClient elasticClient)
{
    var customers = new List<Customer>();
    var searchResult = elasticClient.Search<Customer>(s => s.Index(IndexAlias.ForCustomers())
                          .Size(10000).SearchType(SearchType.Scan).Scroll("1m"));

    do
    {
        var result = searchResult;
        searchResult = elasticClient.Scroll<Customer>("1m", result.ScrollId);
        customers.AddRange(searchResult.Documents);
    } while (searchResult.IsValid && searchResult.Documents.Any());

    return customers.ToArray();
}
Мортен Хольмгаард
источник
0

Если вы хотите получить более 10000 результатов, то во всех узлах данных использование памяти будет очень высоким, потому что он должен возвращать больше результатов в каждом запросе запроса. Тогда, если у вас будет больше данных и больше осколков, объединение этих результатов будет неэффективным. Также es кэширует контекст фильтра, следовательно, снова больше памяти. Вы должны методом проб и ошибок, сколько именно вы берете. Если вы получаете много запросов в маленьком окне, вы должны выполнить несколько запросов для более чем 10 КБ и объединить их самостоятельно в код, который должен занять меньше памяти приложения, чем если вы увеличите размер окна.

Амритенду
источник
0

2) Мне не кажется, что API прокрутки - вариант для меня, но мне нужно увеличить index.max_result_window. У кого-нибудь есть опыт с этим?

-> Вы можете определить это значение в шаблонах индексов, шаблон es будет применим только для новых индексов, поэтому вам нужно либо удалить старые индексы после создания шаблона, либо подождать, пока новые данные будут введены в elasticsearch.

{"order": 1, "template": "index_template *", "settings": {"index.number_of_replicas": "0", "index.number_of_shards": "1", "index.max_result_window": 2147483647},

Синдху
источник
0

В моем случае похоже, что уменьшение результатов с помощью префиксов from & size к запросу устранит ошибку, поскольку нам не нужны все результаты:

GET widgets_development/_search
{
  "from" : 0, 
  "size": 5,
  "query": {
    "bool": {}
  },
  "sort": {
    "col_one": "asc"
  }
}
FlimFlam Vir
источник