Elasticsearch SQL wie Unterabfrage-Aggregation

8

Ich spiele mit ES herum, um zu verstehen, ob es die meisten meiner Szenarien abdecken kann. Ich bin an dem Punkt, an dem ich feststecke, wie ich ein bestimmtes Ergebnis erreichen kann, das in SQL ziemlich einfach ist.

Dies ist das Beispiel

In elastisch habe ich einen Index mit diesen Dokumenten

%Vor%

Wenn ich gerne wissen möchte, wie viele Früchte in verschiedenen Ladengeschäften in einem bestimmten Datumsbereich in SQL gebissen werden, schreibe ich so etwas

%Vor%

Das Ergebnis ist ungefähr so ​​

%Vor%

Hast du eine Idee, wie ich das gleiche Ergebnis in Elastic mit Aggregation erreichen kann?

In ein paar Worten sind die Probleme, mit denen ich mich konfrontiert sehe:

  1. Wie bereitet man eine Untermenge von Daten vor der Aggregation auf (wie in diesem Beispiel die letzte Reihe im Bereich für jede Frucht)
  2. So gruppieren Sie Ergebnisse nach mehreren Feldern

Danke

    
Simone Belia 24.06.2016, 13:04
quelle

2 Antworten

2

Wie ich es verstehe, gibt es keine Möglichkeit, das Aggregationsergebnis im Filter der gleichen Abfrage anzugeben. So können Sie nur einen Teil des Puzzles mit einer einzigen Abfrage lösen:

%Vor%

Damit haben Sie alle Dokumente innerhalb des Datumsbereichs, und Sie haben Bucket-Zählungen, sortiert nach Term, gesammelt, so dass das maximale Datum an der Spitze liegt. Der Client kann diesen ersten Bucket analysieren (sowohl Anzahl als auch Wert) und dann die Dokumente für diesen Datumswert übernehmen. Für eine bestimmte Anzahl von Früchten verwenden Sie einfach eine verschachtelte Kardinalitätsaggregation.

Ja, die Abfrage liefert viel mehr Informationen als benötigt, aber das ist das Leben:)

    
xeye 30.06.2016 20:23
quelle
1

Natürlich gibt es keinen direkten Weg von SQL zur DSL von Elasticsearch, aber es gibt einige ziemlich häufige Korrelationen.

Für den Anfang wird jede GROUP BY / HAVING zu einer Aggregation führen. Die normale Abfragesemantik kann im Allgemeinen (und mehr) von der Query DSL abgedeckt werden.

  

Wie bereitet man eine Untermenge von Daten vor der Aggregation auf (wie in diesem Beispiel die letzte Reihe im Bereich für jede Frucht)

Sie fragen also nach zwei verschiedenen Dingen.

  

Wie bereitet man eine Untermenge von Daten vor der Aggregation auf?

Dies ist die Abfragephase.

  

(wie in diesem Beispiel die letzte Zeile im Bereich für jede Frucht)

Sie fragen es technisch, um zu aggregieren, um die Antwort auf dieses Beispiel zu erhalten: keine normale Abfrage. In Ihrem Beispiel tun Sie MAX , um das zu erhalten, was mit einer GROUP BY geschieht, um es zu bekommen.

  

So gruppieren Sie Ergebnisse nach mehreren Feldern

Es kommt darauf an. Möchten Sie, dass sie abgestuft sind (im Allgemeinen, ja) oder wollen Sie sie zusammen.

Wenn Sie mehrere Ebenen verwenden möchten, verwenden Sie nur Unteraggregationen, um zu erhalten, was Sie wollen. Wenn Sie sie kombinieren möchten, verwenden Sie im Allgemeinen nur eine filters -Aggregation für die verschiedenen Gruppierungen.

Alles wieder zusammensetzen: Sie möchten den letzten Einkauf pro Obst, der einen gewissen gefilterten Zeitraum hat. Die Datumsbereiche sind nur normale Abfragen / Filter:

%Vor%

Damit wird kein Dokument in die Anfrage aufgenommen, das nicht innerhalb dieser Datumsbereiche für beide Felder liegt (effektiv ein AND ). Weil ich einen Filter verwendet habe, ist er nicht gecodiert und kann nicht zwischengespeichert werden.

Jetzt müssen Sie mit der Aggregation beginnen, um den Rest der Informationen zu erhalten. Beginnen wir mit der Annahme, dass die Dokumente mit dem obigen Filter gefiltert wurden, um das zu vereinfachen, was wir betrachten. Wir werden es am Ende kombinieren.

%Vor%

Sie möchten "size" : 0 auf der obersten Ebene, weil Sie sich keine Gedanken über Treffer machen. Sie möchten nur aggregierte Ergebnisse.

Ihre erste Aggregation wurde tatsächlich nach dem letzten Datum gruppiert. Ich habe es ein wenig geändert, um es ein wenig realistischer zu machen ( jeden Tag), aber es ist im Grunde dasselbe. Wie Sie MAX verwenden, könnten wir eine terms -Aggregation mit "size": 1 verwenden, aber das ist wahrer , als ob Sie es bei einem Datum (und vermutlich auch mal!) Tun würden. ) ist involviert. Ich habe es auch gebeten, Tage in den passenden Dokumenten zu ignorieren, die keine Daten haben (da es von Anfang bis Ende geht, interessieren wir uns eigentlich nicht für diese Tage).

Wenn Sie wirklich nur den letzten Tag wollten, könnten Sie eine Pipeline-Aggregation verwenden, um alles außer dem maximalen Bucket zu löschen. Eine realistische Verwendung dieses Anforderungstyps würde jedoch den gesamten Datumsbereich erfordern.

Also fahren wir fort, indem wir nach Speicher gruppieren, was Sie wollen. Dann unterteilen wir uns nach Personen ( BiteBy ). Dies gibt Ihnen die Anzahl implizit.

Alles wieder zusammensetzen:

%Vor%

Hinweis: So habe ich die Daten indexiert.

%Vor%

Es ist kritisch , dass Ihre Zeichenfolgewerte, auf denen Sie aggregieren möchten (Store und Person), not_analyzed string s ( keyword in ES 5.0) sind! Ansonsten wird es Felddaten verwenden, und das ist keine gute Sache.

Die Zuordnungen würden in ES 1.x / ES 2.x wie folgt aussehen:

%Vor%

All dies zusammen, und Sie erhalten die Antwort als:

%Vor%     
pickypg 30.06.2016 23:34
quelle