Elasticsearch 2.1: la finestra dei risultati è troppo grande (index.max_result_window)


88

Recuperiamo informazioni da Elasticsearch 2.1 e consentiamo all'utente di sfogliare i risultati. Quando l'utente richiede un numero di pagina elevato, viene visualizzato il seguente messaggio di errore:

La finestra dei risultati è troppo grande, da + la dimensione deve essere minore o uguale a: [10000] ma era [10020]. Vedere l'API di scorrimento per un modo più efficiente per richiedere set di dati di grandi dimensioni. Questo limite può essere impostato modificando il parametro del livello di indice [index.max_result_window]

Il documento elastico dice che ciò è dovuto all'elevato consumo di memoria e all'utilizzo dell'API di scorrimento:

Valori superiori a quelli che possono consumare blocchi significativi di memoria heap per ricerca e per frammento che esegue la ricerca. È più sicuro lasciare questo valore poiché si tratta di utilizzare l'API di scorrimento per qualsiasi scorrimento profondo https://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

Il fatto è che non voglio recuperare grandi set di dati. Voglio solo recuperare una fetta dal set di dati che è molto in alto nel set di risultati. Anche il documento a scorrimento dice:

Lo scorrimento non è inteso per le richieste degli utenti in tempo reale https://www.elastic.co/guide/en/elasticsearch/reference/2.2/search-request-scroll.html

Questo mi lascia con alcune domande:

1) Il consumo di memoria sarebbe davvero inferiore (se sì perché) se utilizzo l'API di scorrimento per scorrere fino al risultato 10020 (e ignoro tutto ciò che è inferiore a 10000) invece di eseguire una richiesta di ricerca "normale" per il risultato 10000-10020?

2) Non sembra che l'API di scorrimento sia un'opzione per me ma che devo aumentare "index.max_result_window". Qualcuno ha esperienza con questo?

3) Esistono altre opzioni per risolvere il mio problema?

Risposte:


80

Se è necessaria un'impaginazione profonda, una possibile soluzione è aumentare il valore max_result_window. Puoi usare curlper farlo dalla riga di comando della shell:

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

Non ho notato un aumento dell'utilizzo della memoria, per valori di ~ 100k.


Ho lo stesso errore '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.')Ha detto che ha 4719 pagine (ogni pagina 10 risultati). e penso che il tuo suggerimento funzioni.
dotslash

1
Questa è una buona soluzione per piccole quantità di documenti inferiori a 500000
Ezzat

2
Sto usando ES v2.2.0 e ho dovuto cambiare il payload { "max_result_window" : 500000 }per farlo funzionare. Quindi il comando del ricciolo è diventato -curl -XPUT "http://localhost:9200/my_index/_settings" -d '{ "max_result_window" : 500000 }'
Parin Porecha

3
per coloro che ottengono un errore di intestazione con questo comando per la versione più recente di elasticsearch, è necessario passare anche l'intestazione, curl -XPUT " localhost: 9200 / my_index / _settings " -H "Content-Type: application / json" -d '{ "index": {"max_result_window": 50000}} '
Sabato

32

La soluzione giusta sarebbe usare lo scorrimento.
Tuttavia, se desideri estendere i risultati searchrestituiti oltre 10.000 risultati, puoi farlo facilmente con Kibana:

Vai a Dev Toolse pubblica quanto segue nel tuo indice (nome_indice), specificando quale sarebbe la nuova finestra dei risultati massimi

inserisci qui la descrizione dell'immagine

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

Se tutto va bene, dovresti vedere la seguente risposta positiva:

{
  "acknowledged": true
}

1
Ho provato a seguire il modo di farlo nel codice elasticsearch (put_settings ecc ..) e ho raggiunto molti errori. Questo mi fa risparmiare ore! Grazie!
cpres il

25

Le pagine seguenti nella documentazione elastica parlano del deep paging:

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

A seconda delle dimensioni dei documenti, del numero di frammenti e dell'hardware in uso, l'impaginazione da 10.000 a 50.000 risultati (da 1.000 a 5.000 pagine) dovrebbe essere perfettamente fattibile. Ma con valori abbastanza grandi, il processo di ordinamento può diventare davvero molto pesante, utilizzando enormi quantità di CPU, memoria e larghezza di banda. Per questo motivo, sconsigliamo vivamente la paginazione profonda.


1
Quindi qui, dovremmo abbandonare l'impaginazione profonda, giusto? Fondamentalmente non ha senso impaginare 4000 pagine per un singolo visualizzatore. Diciamo, ricerca su google, difficilmente scorriamo alla pagina 8 o 9 per controllare i risultati. Di solito ci occupiamo solo delle prime 3-5 pagine che Google ci fornisce.
dotslash

2
Possiamo usare l'API di scorrimento nel caso in cui abbiamo bisogno di una paginazione profonda?
Abhi.G

3
Ma quando abilitiamo la funzione di ordinamento, diciamo su un sito di e-commerce. quando l'utente desidera vedere gli articoli con il prezzo più alto. Il risultato sarà diverso quando ordiniamo per prezzo più alto rispetto a quando ordiniamo per pagina più bassa ma andiamo all'ultima pagina, giusto? poiché limitiamo il numero di risultati è possibile accedere. qualche soluzione per questo?
MR Murazza

3

Utilizza l'API di scorrimento per ottenere più di 10000 risultati.

Esempio di scorrimento nell'API ElasticSearch NEST

L'ho usato in questo modo:

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

Se si desiderano più di 10000 risultati, in tutti i nodi di dati l'utilizzo della memoria sarà molto elevato perché deve restituire più risultati in ogni richiesta di query. Quindi se hai più dati e più frammenti, l'unione di questi risultati sarà inefficiente. Inoltre memorizza nella cache il contesto del filtro, quindi ancora più memoria. Devi provare ed errore quanto stai prendendo esattamente. Se ricevi molte richieste in una finestra piccola, dovresti fare più query per più di 10k e unirle da solo nel codice, che dovrebbe richiedere meno memoria dell'applicazione se aumenti la dimensione della finestra.


0

2) Non sembra che l'API di scorrimento sia un'opzione per me ma che devo aumentare "index.max_result_window". Qualcuno ha esperienza con questo?

-> Puoi definire questo valore nei modelli di indice, il modello es sarà applicabile solo ai nuovi indici, quindi devi eliminare i vecchi indici dopo aver creato il modello o attendere che i nuovi dati vengano importati in elasticsearch.

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


0

Nel mio caso sembra che ridurre i risultati tramite i prefissi from e size alla query rimuoverà l'errore poiché non abbiamo bisogno di tutti i risultati:

GET widgets_development/_search
{
  "from" : 0, 
  "size": 5,
  "query": {
    "bool": {}
  },
  "sort": {
    "col_one": "asc"
  }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.