Elasticsearch 2.1: Okno wyników jest za duże (index.max_result_window)

86

Pobieramy informacje z Elasticsearch 2.1 i pozwalamy użytkownikowi przeglądać wyniki. Gdy użytkownik zażąda wysokiego numeru strony, otrzymamy następujący komunikat o błędzie:

Okno wyników jest zbyt duże, rozmiar od + musi być mniejszy lub równy: [10000], ale był [10020]. Zobacz przewijany interfejs API, aby uzyskać bardziej efektywny sposób żądania dużych zestawów danych. Limit ten można ustawić, zmieniając parametr poziomu indeksu [index.max_result_window]

Elastyczna dokumentacja mówi, że dzieje się tak z powodu dużego zużycia pamięci i korzystania z przewijanego interfejsu API:

Wartości wyższe niż mogą zużywać znaczące fragmenty pamięci sterty na wyszukiwanie i na fragment wykonujący wyszukiwanie. Najbezpieczniej jest pozostawić tę wartość, ponieważ jest to użycie interfejsu API przewijania do dowolnego głębokiego przewijania https://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

Chodzi o to, że nie chcę pobierać dużych zestawów danych. Chcę tylko pobrać wycinek ze zbioru danych, który jest bardzo wysoko w zestawie wyników. Również przewijany dokument mówi:

Przewijanie nie jest przeznaczone dla żądań użytkowników w czasie rzeczywistym https://www.elastic.co/guide/en/elasticsearch/reference/2.2/search-request-scroll.html

Pozostaje mi kilka pytań:

1) Czy zużycie pamięci byłoby naprawdę niższe (jeśli tak, dlaczego), gdybym użyłby przewijanego interfejsu API do przewijania w górę do wyniku 10020 (i zignorował wszystko poniżej 10000) zamiast wykonywać „normalne” żądanie wyszukiwania wyniku 10000-10020?

2) Nie wygląda na to, że scrolling API jest dla mnie opcją, ale muszę zwiększyć "index.max_result_window". Czy ktoś ma z tym jakieś doświadczenie?

3) Czy są jakieś inne możliwości rozwiązania mojego problemu?

Ronald
źródło

Odpowiedzi:

79

Jeśli potrzebujesz głębokiej paginacji, jednym z możliwych rozwiązań jest zwiększenie wartości max_result_window. Możesz curlto zrobić z linii poleceń powłoki:

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

Nie zauważyłem zwiększonego użycia pamięci, dla wartości ~ 100k.

Andrey Morozov
źródło
Mam ten sam błąd '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.')Mówi się, że ma 4719 stron (każda strona 10 wyników). i myślę, że twoja sugestia działa.
dotslash,
1
To dobre rozwiązanie dla małej ilości dokumentów poniżej 500000
Ezzat
2
Używam ES v2.2.0 i musiałem zmienić ładunek na, { "max_result_window" : 500000 }aby to zadziałało. Tak więc polecenie curl stało się -curl -XPUT "http://localhost:9200/my_index/_settings" -d '{ "max_result_window" : 500000 }'
Parin Porecha
3
dla tych, którzy otrzymują błąd nagłówka przy użyciu tego polecenia dla nowszej wersji elastycznego wyszukiwania, należy również przekazać nagłówek, curl -XPUT " localhost: 9200 / my_index / _settings " -H "Content-Type: application / json" -d '{ "index": {"max_result_window": 50000}} '
Satys,
32

Właściwym rozwiązaniem byłoby użycie przewijania.
Jeśli jednak chcesz przedłużyć wynikisearch zwroty powyżej 10000 wyników, możesz to łatwo zrobić z Kibana:

Przejdź do Dev Toolsi po prostu opublikuj poniższy kod w swoim indeksie (twoja_nazwa_indeksu), określając, jakie będzie nowe okno maksymalnych wyników

wprowadź opis obrazu tutaj

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

Jeśli wszystko pójdzie dobrze, powinieneś zobaczyć następującą odpowiedź:

{
  "acknowledged": true
}
Guy Dubrovski
źródło
1
Próbowałem postępować zgodnie z instrukcją w kodzie elastycznego wyszukiwania (put_settings itp.) I napotkałem wiele błędów. To oszczędza mi godziny! Dziękuję Ci!
cpres
24

Poniższe strony w dokumentacji elastycznej mówią o głębokim stronicowaniu:

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

W zależności od rozmiaru dokumentów, liczby fragmentów i używanego sprzętu, stronicowanie od 10 000 do 50 000 wyników (od 1 000 do 5 000 stron) powinno być całkowicie wykonalne. Ale przy wystarczająco dużych wartościach proces sortowania może być naprawdę bardzo ciężki, wykorzystując ogromne ilości procesora, pamięci i przepustowości. Z tego powodu zdecydowanie odradzamy głębokie stronicowanie.

Ronald
źródło
1
Więc tutaj powinniśmy porzucić głęboką paginację, prawda? W zasadzie nie ma sensu stronicować 4000 stron dla jednej przeglądarki. Powiedzmy, wyszukiwarka Google, prawie nie przewijamy do strony 8 lub 9, aby sprawdzić wyniki. Zwykle zajmujemy się tylko 3–5 najlepszymi stronami, które udostępnia nam Google.
dotslash,
2
Czy możemy użyć scroll API na wypadek, gdybyśmy potrzebowali głębokiej paginacji?
Abhi.G
3
Ale kiedy włączamy funkcję sortowania, powiedzmy w witrynie eCommerce. gdy użytkownik chce zobaczyć przedmioty o najwyższej cenie. Wynik będzie inny, gdy posortujemy według najwyższej ceny w porównaniu z sortowaniem według najniższej strony, ale przejdziemy do ostatniej strony, prawda? ponieważ ograniczamy liczbę wyników, do których można uzyskać dostęp. jakieś obejście tego?
MR Murazza
3

Użyj interfejsu API Scroll, aby uzyskać ponad 10000 wyników.

Przykład przewijania w ElasticSearch NEST API

Użyłem tego w ten sposób:

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
źródło
0

Jeśli chcesz uzyskać więcej niż 10000 wyników, wówczas we wszystkich węzłach danych użycie pamięci będzie bardzo wysokie, ponieważ musi zwracać więcej wyników w każdym żądaniu zapytania. Jeśli masz więcej danych i więcej fragmentów, scalanie tych wyników będzie nieefektywne. Również buforuje kontekst filtru, stąd znowu więcej pamięci. Musisz próbować i popełniać błędy, ile dokładnie bierzesz. Jeśli otrzymujesz wiele żądań w małym oknie, powinieneś wykonać wiele zapytań dla więcej niż 10k i scalić je samodzielnie w kodzie, co ma zająć mniej pamięci aplikacji, niż jeśli zwiększysz rozmiar okna.

Amritendu
źródło
0

2) Nie wygląda na to, że scrolling API jest dla mnie opcją, ale muszę zwiększyć "index.max_result_window". Czy ktoś ma z tym jakieś doświadczenie?

-> Możesz zdefiniować tę wartość w szablonach indeksów, szablon es będzie miał zastosowanie tylko do nowych indeksów, więc musisz albo usunąć stare indeksy po utworzeniu szablonu, albo poczekać na pozyskanie nowych danych w elastynsearch.

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

Sindhu
źródło
0

W moim przypadku wygląda na to, że zmniejszenie wyników za pomocą prefiksów from & size do zapytania usunie błąd, ponieważ nie potrzebujemy wszystkich wyników:

GET widgets_development/_search
{
  "from" : 0, 
  "size": 5,
  "query": {
    "bool": {}
  },
  "sort": {
    "col_one": "asc"
  }
}
FlimFlam Vir
źródło