Problem: Abrufen von mehr als 10.000 Ergebnissen in der elastischen Suche über die Suche in einer GET/Suchabfrage.
GET hostname:port /myIndex/_search {
"size": 10000,
"query": {
"term": { "field": "myField" }
}
}
Ich habe die Größenoption verwendet und wusste, dass:
index.max_result_window = 100000
Wenn jedoch meine Abfrage beispielsweise die Größe von 650.000 Dokumenten oder sogar mehr hat, wie kann ich dann alle Ergebnisse in einem GET abrufen?
Ich habe über SCROLL, FROM-TO und die PAGINATION-API gelesen, aber alle liefern niemals mehr als 10 KB.
Dies ist das Beispiel aus dem Elasticsearch Forum, das ich verwendet habe:
GET /_search?scroll=1m
Kann jemand ein Beispiel geben, in dem Sie alle Dokumente für eine GET-Suchabfrage abrufen können?
Vielen Dank.
Scroll ist der Weg, wenn Sie eine große Anzahl von Dokumenten abrufen möchten, und zwar in dem Sinne, dass sie die 10000-Standardgrenze überschreitet, die angehoben werden kann.
Die erste Anforderung muss die gewünschte Abfrage und den Parameter scroll
mit duration angeben, bevor der Suchkontext abläuft (1 Minute im Beispiel unten).
POST /index/type/_search?scroll=1m
{
"size": 1000,
"query": {
"match" : {
"title" : "elasticsearch"
}
}
}
In der Antwort auf diesen ersten Anruf erhalten Sie einen _scroll_id
, den Sie für den zweiten Anruf verwenden müssen:
POST /_search/scroll
{
"scroll" : "1m",
"scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="
}
In jeder weiteren Antwort erhalten Sie einen neuen _scroll_id
, den Sie für den nächsten Anruf verwenden müssen, bis Sie die benötigte Menge an Dokumenten abgerufen haben.
Im Pseudocode sieht das also ungefähr so aus:
# first request
response = request('POST /index/type/_search?scroll=1m')
docs = [ response.hits ]
scroll_id = response._scroll_id
# subsequent requests
while (true) {
response = request('POST /_search/scroll', scroll_id)
docs.Push(response.hits)
scroll_id = response._scroll_id
}
bitte schön:
GET /_search
{
"size": "10000",
"query": {
"match_all": {"boost" : "1.0" }
}
}
Wir sollten diesen Ansatz jedoch größtenteils vermeiden, um eine große Menge von Dokumenten gleichzeitig abzurufen, da dies die Datennutzung und den Overhead erhöhen kann.
Eine weitere Option ist das search_after Tag. Zusammen mit einem Sortiermechanismus können Sie Ihr letztes Element in der ersten Zeile speichern und dann nach Ergebnissen fragen, die auf dieses letzte Element folgen.
GET Twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "elasticsearch"
}
},
"search_after": [1463538857, "654323"],
"sort": [
{"date": "asc"},
{"_id": "desc"}
]
}
Arbeitete für mich. Bis jetzt ist es jedoch nicht einfach, mehr als 10.000 Dokumente zu erhalten.
Ich kann einen besseren Weg vorschlagen, dies zu tun. Ich denke, Sie versuchen, mehr als 10.000 Datensätze zu bekommen. Versuchen Sie es wie folgt und Sie werden auch Millionen von Datensätzen erhalten.
Definieren Sie Ihren Kunden.
client = Elasticsearch(['http://localhost:9200'])
search = Search(using=client)
Überprüfen Sie die Gesamtzahl der Treffer.
results = search.execute()
results.hits.total
s = Search(using=client)
Notieren Sie Ihre Anfrage.
s = s.query(..write your query here...)
Dump die Daten in einen Datenrahmen mit Scan. Scan speichert alle Daten in Ihrem Datenrahmen, auch wenn sie in Milliardenhöhe vorliegen. Seien Sie also vorsichtig.
results_df = pd.DataFrame((d.to_dict() for d in s.scan()))
Schauen Sie sich Ihren Datenrahmen an.
results_df
Wenn Sie eine Fehlermeldung mit der Suchfunktion erhalten, gehen Sie wie folgt vor:
from elasticsearch_dsl import Search
nodeJS scroll Beispiel mit elascticsearch :
const elasticsearch = require('elasticsearch');
const elasticSearchClient = new elasticsearch.Client({ Host: 'esURL' });
async function getAllData(query) {
const result = await elasticSearchClient.search({
index: '*',
scroll: '10m',
size: 10000,
body: query,
});
const retriever = async ({
data,
total,
scrollId,
}) => {
if (data.length >= total) {
return data;
}
const result = await elasticSearchClient.scroll({
scroll: '10m',
scroll_id: scrollId,
});
data = [...data, ...result.hits.hits];
return retriever({
total,
scrollId: result._scroll_id,
data,
});
};
return retriever({
total: result.hits.total,
scrollId: result._scroll_id,
data: result.hits.hits,
});
}
Schauen Sie sich search_after documentation an
Beispielabfrage als Hash in Ruby:
query = {
size: query_size,
query: {
multi_match: {
query: "black",
fields: [ "description", "title", "information", "params" ]
}
},
search_after: [after],
sort: [ {id: "asc"} ]
}
Wenn mehr als 10000 Ergebnisse vorliegen, besteht die einzige Möglichkeit, den Rest zu erhalten, darin, Ihre Abfrage in mehrere, verfeinerte Abfragen mit strengeren Filtern aufzuteilen, sodass jede Abfrage weniger als 10000 Ergebnisse zurückgibt. Kombinieren Sie anschließend die Abfrageergebnisse, um die vollständige Zielergebnismenge zu erhalten.
Diese Beschränkung auf 10000 Ergebnisse gilt für Webservices, die vom ElasticSearch-Index unterstützt werden, und es führt kein Weg daran vorbei, dass der Webservice ohne die Verwendung von ElasticSearch erneut implementiert werden muss.