Elasticsearch 2.1: a janela de resultados é muito grande (index.max_result_window)

86

Nós recuperamos informações do Elasticsearch 2.1 e permitimos que o usuário navegue pelos resultados. Quando o usuário solicita um número alto de página, obtemos a seguinte mensagem de erro:

A janela de resultados é muito grande, o tamanho de + deve ser menor ou igual a: [10000], mas era [10020]. Consulte a API de rolagem para obter uma maneira mais eficiente de solicitar grandes conjuntos de dados. Este limite pode ser definido alterando o parâmetro de nível de índice [index.max_result_window]

O documento elástico diz que isso se deve ao alto consumo de memória e ao uso da API de rolagem:

Valores maiores que podem consumir pedaços significativos de memória heap por pesquisa e por fragmento que executa a pesquisa. É mais seguro deixar esse valor, pois é um uso da API de rolagem para qualquer rolagem profunda https://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

O fato é que não quero recuperar grandes conjuntos de dados. Desejo apenas recuperar uma fatia do conjunto de dados que está muito no topo do conjunto de resultados. Além disso, o documento de rolagem diz:

A rolagem não se destina a solicitações de usuários em tempo real https://www.elastic.co/guide/en/elasticsearch/reference/2.2/search-request-scroll.html

Isso me deixa com algumas perguntas:

1) O consumo de memória seria realmente menor (algum em caso afirmativo, por que) se eu usar a API de rolagem para rolar para cima até o resultado 10020 (e desconsiderar tudo abaixo de 10000) em vez de fazer uma solicitação de pesquisa "normal" para o resultado 10000-10020?

2) Não parece que a API de rolagem seja uma opção para mim, mas tenho que aumentar "index.max_result_window". Alguém tem alguma experiência com isto?

3) Existem outras opções para resolver meu problema?

Ronald
fonte

Respostas:

79

Se você precisar de paginação profunda, uma solução possível é aumentar o valor max_result_window. Você pode usar curlpara fazer isso na linha de comando do shell:

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

Não notei aumento no uso de memória, para valores de ~ 100k.

Andrey Morozov
fonte
Tenho o mesmo erro '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.')Dizia que tem 4719 páginas (a cada página 10 resultados). e acho que sua sugestão funciona.
dotslash de
1
Esta é uma boa solução para pequenas quantidades de documentos com menos de 500.000
Ezzat
2
Estou usando o ES v2.2.0 e tive que alterar a carga útil para { "max_result_window" : 500000 }para que isso funcione. Assim, o comando curl tornou-se -curl -XPUT "http://localhost:9200/my_index/_settings" -d '{ "max_result_window" : 500000 }'
Parin Porecha
3
para aqueles que recebem o erro de cabeçalho com este comando para a versão mais recente do elasticsearch, você precisa passar o cabeçalho também, curl -XPUT " localhost: 9200 / my_index / _settings " -H "Content-Type: application / json" -d '{ "index": {"max_result_window": 50000}} '
Sábado
32

A solução certa seria usar a rolagem.
No entanto, se você quiser estender os searchretornos de resultados para além de 10.000 resultados, pode fazer isso facilmente com Kibana:

Acesse Dev Toolse apenas postar o seguinte em seu índice (your_index_name), especificando qual seria a nova janela de resultado máximo

insira a descrição da imagem aqui

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

Se tudo correr bem, você deverá ver a seguinte resposta de sucesso:

{
  "acknowledged": true
}
Guy Dubrovski
fonte
1
Tentei seguir a forma de fazer isso no código do elasticsearch (put_settings etc.) e achei muitos erros. Isso me economiza horas! Obrigado!
cpres
24

As páginas a seguir na documentação elástica falam sobre paginação profunda:

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

Dependendo do tamanho dos seus documentos, do número de fragmentos e do hardware que você está usando, a paginação de 10.000 a 50.000 resultados (1.000 a 5.000 páginas) de profundidade deve ser perfeitamente factível. Mas com valores de origem suficientemente grandes, o processo de classificação pode se tornar muito pesado, usando grandes quantidades de CPU, memória e largura de banda. Por esse motivo, desaconselhamos vivamente a paginação profunda.

Ronald
fonte
1
Portanto, devemos abandonar a paginação profunda, certo? Basicamente, não há significado de paginar 4.000 páginas para um único visualizador. Digamos, pesquisa no google, dificilmente rolamos para a página 8 ou 9 para verificar os resultados. Normalmente, cuidamos apenas das 3 a 5 páginas principais que o Google nos fornece.
dotslash
2
Podemos usar a API de rolagem no caso de precisarmos de paginação profunda?
Abhi.G
3
Mas quando habilitamos o recurso de classificação, digamos em um site de comércio eletrônico. quando o usuário deseja ver itens com preço mais alto. O resultado será diferente quando ordenamos pelo preço mais alto em comparação com quando ordenamos pela página mais baixa, mas vamos para a última página, certo? pois limitamos o número de resultados que podem ser acessados. alguma solução para isso?
MR Murazza de
3

Use a API Scroll para obter mais de 10.000 resultados.

Exemplo de rolagem na API ElasticSearch NEST

Eu usei assim:

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();
}
Morten Holmgaard
fonte
0

Se você quiser mais de 10.000 resultados, em todos os nós de dados, o uso de memória será muito alto, porque deve retornar mais resultados em cada solicitação de consulta. Então, se você tiver mais dados e mais fragmentos, mesclar esses resultados será ineficiente. Também armazena em cache o contexto do filtro, portanto, mais memória. Você tem que tentar e errar o quanto exatamente você está tomando. Se você estiver recebendo muitas solicitações em uma janela pequena, deve fazer várias consultas por mais de 10k e mesclá-las por conta própria no código, o que deve ocupar menos memória do aplicativo do que se você aumentar o tamanho da janela.

Amritendu
fonte
0

2) Não parece que a API de rolagem seja uma opção para mim, mas tenho que aumentar "index.max_result_window". Alguém tem alguma experiência com isto?

-> Você pode definir esse valor em modelos de índice, o modelo es será aplicável apenas para novos índices, portanto, você deve excluir os índices antigos após criar o modelo ou aguardar que novos dados sejam inseridos no elasticsearch.

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

Sindhu
fonte
0

No meu caso, parece que reduzir os resultados por meio dos prefixos de & size para a consulta removerá o erro, pois não precisamos de todos os resultados:

GET widgets_development/_search
{
  "from" : 0, 
  "size": 5,
  "query": {
    "bool": {}
  },
  "sort": {
    "col_one": "asc"
  }
}
FlimFlam Vir
fonte