Engineering

Eine Einführung in Elasticsearch SQL mit praktischen Beispielen – Teil 2

Teil 1 dieser Reihe Einführung in Elasticsearch SQL bot eine Einführung zum neuen Elasticsearch SQL-Feature sowie zur _translate-API. In diesem Beitrag setzen wir die Reihe fort und stellen komplexere Features vor. Im Anschluss betrachten wir einige der derzeitigen Einschränkungen, auf die Anwender in diesem ersten Release von SQL stoßen können. Und schließlich beenden wir diesen Teil mit einer Vorschau auf unsere zukünftigen Pläne.

Wir möchten Sie daran erinnern, dass alle Leser die auf demo.elastic.co bereitgestellten Beispiele ausführen können. Sie können auch warten, bis der Datensatz über die Kibana-Konsole verfügbar ist. Alle in dieser Reihe verwendeten Datensätze wurden indexiert, wobei auch SQL über die Kibana-Konsole verfügbar ist. Für jedes Beispiel sind Links zu demo.elastic.co verfügbar. Alternativ können alle Abfragen als ein einzelner Thread in der Kibana-Demokonsole angezeigt werden.

Komplexe Beispiele und die Vorteile von Elasticsearch

Gruppieren

Das Aggregation-Framework von Elasticsearch, das in der Lage ist, Milliarden von Datenpunkten zusammenzufassen, ist eines der leistungsstärksten und beliebtesten Features des Stacks. Im Hinblick auf seinen Funktionsumfang entspricht es dem Operator GROUP BY in SQL. Neben einigen Beispielen für die GROUP BY-Funktionen verwenden wir an dieser Stelle auch wieder die translate-API, um die entsprechenden Aggregationen aufzuzeigen.

„Finde die durchschnittliche Flugzeit pro Herkunfts- und Zielland für Flüge nach London. Führe die Ergebnisse in alphabetischer Reihenfolge der Länder auf.“

Probieren Sie es auf demo.elastic.co aus.

sql> SELECT AVG(FlightTimeHour) Avg_Flight_Time, OriginCountry FROM flights GROUP BY OriginCountry ORDER BY OriginCountry LIMIT 5;
 Avg_Flight_Time  | OriginCountry
------------------+---------------
9.342180244924574 |AE
13.49582274385201 |AR
4.704097126921018 |AT
15.081367354940724|AU
7.998943401875511 |CA

Die Untersuchung der DSL für diese Abfrage zeigt die Verwendung der verbundenen Aggregation.

{
  "size": 0,
  "_source": false,
  "stored_fields": "_none_",
  "aggregations": {
    "groupby": {
      "composite": {
        "size": 1000,
        "sources": [
          {
            "3471": {
              "terms": {
                "field": "OriginCountry.keyword",
                "order": "asc"
              }
            }
          }
        ]
      },
      "aggregations": {
        "3485": {
          "avg": {
            "field": "FlightTimeHour"
          }
        }
      }
    }
  }
}

Probieren Sie es auf demo.elastic.co aus.

Wir können die Gruppierung auch nach Aliasfeldern durchführen, die mithilfe einer Funktion unter „Select“ definiert sind.

„Finde die Anzahl und die durchschnittliche Flugzeit der Flüge pro Monat.“

POST _xpack/sql
{
  "query":"SELECT COUNT(*), MONTH_OF_YEAR(timestamp) AS month_of_year, AVG(FlightTimeHour) AS Avg_Flight_Time FROM flights GROUP BY month_of_year"
}

Probieren Sie es auf demo.elastic.co aus.

   COUNT(1)    | month_of_year | Avg_Flight_Time 
---------------+---------------+-----------------
1303           |5              |8.628949653846158
8893           |6              |8.520481551839334
2863           |7              |8.463433805045094

Die Verwendung der verbundenen Aggregation hat einen wesentlichen Vorteil: Sie gewährleistet, dass die Implementierung von GROUP BY sogar für Felder mit hoher Kardinalität skalierbar ist und bietet einen Mechanismus zum Streamen aller Buckets einer bestimmten Aggregation mit einem ähnlichen Ergebnis wie beim Scrollen eines Dokuments. Dies stellt zudem sicher, dass die Implementierung nicht von den gleichen Speichereinschränkungen betroffen ist, wie die, die bei der Verwendung der Begriffsaggregation auftreten würden. Es bedeutet jedoch, dass wir die Gruppe derzeit nicht nach einer Metrik sortieren können. Der folgende Code würde beispielsweise zu einem Fehler führen:

POST _xpack/sql/translate
{
  "query":"SELECT AVG(FlightTimeHour) Avg_Flight_Time, OriginCountry FROM flights GROUP BY OriginCountry ORDER BY Avg_Flight_Time"
}

Probieren Sie es auf demo.elastic.co aus.

Filtern von Gruppen

Gruppen können mithilfe der Klausel HAVING gefiltert werden, die auch ein in der Klausel SELECT angegebenes Alias nutzen kann. Einige SQL-Experten sind möglicherweise daran gewöhnt, doch im Allgemeinen ist dies in RDBMS-basierten Implementationen aufgrund der Tatsache, dass die Klausel SELECT nach der Klausel HAVING ausgeführt wird, nicht möglich. Hier wird von der Klausel HAVING ein Alias genutzt, das in der Ausführungsphase deklariert ist. Unser Analyzer ist jedoch so intelligent, dass er vorausschauend agiert und die Deklaration für die Verwendung in HAVING bereits vorab aufnimmt.

„Finde die Anzahl, den Durchschnitt und das 0,95-Quantil von Flügen von jeder Herkunftsstadt, bei denen die durchschnittliche Flugdistanz zwischen 3000 und 4000 Meilen (4828 und 6437 km) liegt.“

Probieren Sie es auf demo.elastic.co aus.

sql> SELECT OriginCityName, ROUND(AVG(DistanceKilometers)) avg_distance, COUNT(*) c, ROUND(PERCENTILE(DistanceKilometers,95)) AS percentile_distance FROM flights GROUP BY OriginCityName HAVING avg_distance BETWEEN 3000 AND 4000;
OriginCityName | avg_distance  |       c       |percentile_distance
---------------+---------------+---------------+-------------------
Verona         |3078           |120            |7927
Vienna         |3596           |120            |7436
Xi'an          |3842           |114            |7964

SQL Elasticsearch nutzt die Pipeline Aggregation von Bucket Selector zur Implementierung der HAVING-Funktionalität und filtert dabei die Werte mithilfe eines parametrisierten Painless-Skripts. Beachten Sie, dass im Folgenden statt der Standardtextvariante automatisch die Variante für keyword (Schlüsselwort) des Felds OriginCityName (Name der Herkunftsstadt) für die Aggregation ausgewählt wird. Die Standardtextvariante würde wahrscheinlich aufgrund der fehlenden Aktivierung der Felddaten einen Fehler generieren. Die Metrikaggregationen avg (Durchschnitt) und percentile (Quantil) bieten ähnliche Funktionen wie die SQL-Varianten.

Probieren Sie es auf demo.elastic.co aus.

{
  "size": 0,
  "_source": false,
  "stored_fields": "_none_",
  "aggregations": {
    "groupby": {
      "composite": {
        "size": 1000,
        "sources": [
          {
            "4992": {
              "terms": {
                "field": "OriginCityName.keyword",
                "order": "asc"
              }
            }
          }
        ]
      },
      "aggregations": {
        "4947": {
          "bucket_selector": {
            "buckets_path": {
              "a0": "5010",
              "a1": "5010"
            },
            "script": {
              "source": "params.v0 <= params.a0 && params.a1 <= params.v1",
              "lang": "painless",
              "params": {
                "v0": 3000,
                "v1": 4000
              }
            },
            "gap_policy": "skip"
          }
        },
        "5010": {
          "avg": {
            "field": "DistanceKilometers"
          }
        },
        "5019": {
          "percentiles": {
            "field": "DistanceKilometers",
            "percents": [
              95
            ],
            "keyed": true,
            "tdigest": {
              "compression": 100
            }
          }
        }
      }
    }
  }
}

Textoperatoren und Relevanz

Eine der Funktionen der Suchmaschine Elasticsearch, die diese von traditionellen relationalen Datenbankmanagementsystemen (RDBMS) abheben, ist ihre Fähigkeit, Übereinstimmungen zu finden, die über ein einfaches Ja/Nein hinausgehen. Hierzu werden die Eigenschaften von textuellen Daten mithilfe einer Relevanzberechnung berücksichtigt. Die Erweiterung der SQL-Syntax ermöglicht es uns, die Funktionalität verfügbar zu machen und über die Leistungsfähigkeit eines traditionellen RDBMS weit hinauszugehen.

Wir führen daher zwei neue Operatoren ein: QUERY und MATCH. Diese entsprechen den zugrunde liegenden Operatoren multi_match und query_string in Elasticsearch. Anwender von Kibana sind mit dem Verhalten des Operators „query_string“ vertraut, da dieser der Standard-Suchleiste zugrunde liegt. Der Operator bietet intelligente Parsing-Funktionen und ermöglicht einen natürlichen Sprachstil für Abfragen. Die Einzelheiten zu diesen beiden Operatoren gehen über den Rahmen dieses Blogs hinaus, doch das Buch The Definitive Guide bietet eine hervorragende Einführung in diese Konzepte.

Betrachten Sie das folgende Beispiel:

„Finde alle verspäteten Flüge am Flughafen Kopenhagen-Kastrup (Ankunft und Abflug) zwischen dem 6. Juni und dem 17. Juni 2018 und sortiere das Ergebnis in chronologischer Reihenfolge.“

Probieren Sie es auf demo.elastic.co aus.

Für den Operator QUERY brauchen wir nicht den vollständigen Titel des Flughafens anzugeben, wir suchen einfach nach Kastrup.

sql> SELECT timestamp, FlightNum, OriginCityName, DestCityName FROM flights WHERE QUERY('Kastrup') AND FlightDelay=true AND timestamp > '2018-06-20' AND timestamp < '2018-06-27' ORDER BY timestamp;
       timestamp        |   FlightNum   |OriginCityName | DestCityName
------------------------+---------------+---------------+---------------
2018-06-21T01:46:28.000Z|57SWSLT        |Copenhagen     |Orlando
2018-06-21T07:28:07.000Z|X43J6GE        |Abu Dhabi      |Copenhagen
2018-06-21T13:36:31.000Z|7T04SK7        |Copenhagen     |Milan
2018-06-22T19:52:15.000Z|NXMN87D        |Mumbai         |Copenhagen
2018-06-23T08:05:02.000Z|YXHMDKV        |Copenhagen     |Oslo
2018-06-25T18:21:04.000Z|2R86JEZ        |Copenhagen     |Shanghai
2018-06-26T22:16:10.000Z|TCE99LO        |Copenhagen     |Edmonton

Wie Sie sehen, braucht das Feld hier nicht angegeben zu werden. Es reicht völlig aus, mithilfe des Operators QUERY nach „kastrup“ zu suchen. Beachten Sie auch, dass sowohl Flüge nach (to) als auch Flüge von from Kopenhagen-Kastrup verspätet waren. Die Abfrage in Elasticsearch sieht wie folgt aus:

Probieren Sie es auf demo.elastic.co aus.

{
  "size": 1000,
  "query": {
    "bool": {
      "filter": [
        {
          "bool": {
            "filter": [
              {
                "bool": {
                  "filter": [
                    {
                      "query_string": {
                        "query": "Kastrup",
                        "fields": [],
                        "type": "best_fields",
                        "default_operator": "or",
                        "max_determinized_states": 10000,
                        "enable_position_increments": true,
                        "fuzziness": "AUTO",
                        "fuzzy_prefix_length": 0,
                        "fuzzy_max_expansions": 50,
                        "phrase_slop": 0,
                        "escape": false,
                        "auto_generate_synonyms_phrase_query": true,
                        "fuzzy_transpositions": true,
                        "boost": 1
                      }
                    },
                    {
                      "term": {
                        "FlightDelay": {
                          "value": true,
                          "boost": 1
                        }
                      }
                    }
                  ],
                  "adjust_pure_negative": true,
                  "boost": 1
                }
              },
              {
                "range": {
                  "timestamp": {
                    "from": "2018-06-20",
                    "to": null,
                    "include_lower": false,
                    "include_upper": false,
                    "boost": 1
                  }
                }
              }
            ],
            "adjust_pure_negative": true,
            "boost": 1
          }
        },
        {
          "range": {
            "timestamp": {
              "from": null,
              "to": "2018-06-27",
              "include_lower": false,
              "include_upper": false,
              "boost": 1
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  },
  "_source": {
    "includes": [
      "FlightNum",
      "OriginCityName",
      "DestCityName"
    ],
    "excludes": []
  },
  "docvalue_fields": [
    "timestamp"
  ],
  "sort": [
    {
      "timestamp": {
        "order": "asc"
      }
    }
  ]
}

Für neue Anwender von Elasticsearch stellt dies eine relativ komplexe Abfrage dar. Sie enthält eine boolesche Abfrage (bool) mit einem geschachtelten Bereich (range), Laufzeitbeschränkung (timestamp) und Abfragezeichenfolgeoperator (query_string). Für Anwender, die eine Anwendung von SQL migrieren, war dies wahrscheinlich immer schon eine ziemlich undankbare Aufgabe, ohne dabei zu berücksichtigen, ob die endgültige Abfrage richtig und optimal funktioniert. Der eigentliche Abfragezeichenfolgeoperator (query_string) ist in einen Filter geschachtelt, da keine Relevanz erforderlich ist (die Sortierung erfolgt nach dem Datum), und ermöglicht es uns so, den Filtercache zu nutzen, die Bewertung zu überspringen und die Antwortzeit zu verbessern.

Die Parameter für diese Operatoren sind ebenfalls in SQL verfügbar. Dieses letzte Beispiel veranschaulicht, wie eine MATCH-Abfrage mit mehreren Suchbegriffen über mehrere Felder hinweg eingesetzt wird, um die Suchergebnisse einzuschränken.

„Finde Flüge von oder nach Barcelona, bei denen Gewitterblitze aufgetreten sind.“

Probieren Sie es auf demo.elastic.co aus.

Zu Veranschaulichungszwecken wird das Ergebnis auch anhand der Funktion Score() sortiert und die Relevanzbewertung wird über diese Funktion angezeigt.

sql> SELECT Score(), timestamp, FlightNum, OriginCityName, DestCityName, DestWeather, OriginWeather FROM flights WHERE MATCH('*Weather,*City*', 'Lightning Barcelona', 'type=cross_fields;operator=AND') ORDER BY Score() DESC LIMIT 5;
    SCORE()    |       timestamp        |   FlightNum   |OriginCityName | DestCityName  |    DestWeather    |   OriginWeather
---------------+------------------------+---------------+---------------+---------------+-------------------+-------------------
6.990964       |2018-05-31T06:00:41.000Z|L637ISB        |Barcelona      |Santiago       |Rain               |Thunder & Lightning
6.990964       |2018-06-13T12:23:44.000Z|0GIHB62        |Barcelona      |Buenos Aires   |Clear              |Thunder & Lightning
6.9796515      |2018-06-14T21:04:51.000Z|7GEMEDR        |Barcelona      |Hyderabad      |Thunder & Lightning|Rain
6.9133706      |2018-05-31T01:58:51.000Z|ZTOD7RQ        |Barcelona      |Dubai          |Sunny              |Thunder & Lightning
6.9095163      |2018-06-06T14:02:34.000Z|QSQA5CT        |Barcelona      |Naples         |Rain               |Thunder & Lightning

Wir verwenden Platzhaltermuster, um die Felder anzugeben, für die eine Übereinstimmung gesucht werden soll, und fordern, dass es sich bei der Übereinstimmung um ein boolesches AND (UND) handelt. Für den feldübergreifenden Parameter „cross_fields“ ist es nicht erforderlich, dass die Begriffe alle in einem Feld erscheinen, sondern sie dürfen in unterschiedlichen Feldern vorkommen, vorausgesetzt, dass beide vorhanden sind. In Anbetracht der Struktur der Daten ist dies für die Übereinstimmung unabdingbar.

Die hier angegebenen Beispiele haben Zeilen im Vergleich zu Gruppen zurückgegeben. Die Operatoren QUERY und MATCH können jedoch auch mit einem Operator vom Typ GROUP BY verwendet werden, faktisch eine gefilterte Aggregation für Elasticsearch.

Indexübergreifende Suchen und Aliase

Bisher war das Ziel unserer Abfragen nur eine einzelne Tabelle bzw. ein einzelner Index. Falls wir den Flugindex verdoppeln, indem wir die Dokumente über eine Anforderung zur Neuindexierung kopieren und als neu benannte Version abspeichern, können wir beide Indizes gleichzeitig abfragen, sofern beide Indizes über identische Mappings (Zuordnungen) verfügen. Unterschiede im Mapping würden zu einem Fehler bei der Analyse der Abfrage führen. Wenn Anwender mehrere Indizes gleichzeitig abfragen möchten, können sie diese entweder einem Elasticsearch-Alias hinzufügen oder Platzhalter in der Klausel WHERE nutzen. Im folgenden Beispiel verfügen wir über zwei Indizes „flights“ und „flights-2“ mit dem folgenden „f_alias“-Alias:

POST /_aliases
{
    "actions" : [
       { "add" : { "index" : "flights-2", "alias" : "f_alias" } },
        { "add" : { "index" : "flights", "alias" : "f_alias" } }
    ]
}

Die folgenden Codes sind im Hinblick auf die Logik gleichwertig:

sql> SELECT FlightNum, OriginCityName, DestCityName, DestWeather, OriginWeather FROM flights* ORDER BY timestamp DESC LIMIT 1;
   FlightNum   |OriginCityName | DestCityName  |  DestWeather  | OriginWeather
---------------+---------------+---------------+---------------+---------------
6UPDDGK        |Zurich         |Zurich         |Rain           |Hail
sql> SELECT FlightNum, OriginCityName, DestCityName, DestWeather, OriginWeather FROM f_alias ORDER BY timestamp DESC LIMIT 1;
   FlightNum   |OriginCityName | DestCityName  |  DestWeather  | OriginWeather
---------------+---------------+---------------+---------------+---------------
6UPDDGK        |Zurich         |Zurich         |Rain           |Hail

Probieren Sie es auf demo.elastic.co aus. Unsere Demoumgebung enthält beide Indizes mit vorkonfigurierten Aliasen, damit Benutzer das vorherige Beispiel ausprobieren können.

Wir lockern die oben angegebenen Anforderungen möglicherweise in der Zukunft, doch derzeit vereinfachen sie noch die Logik in diesem ersten Release.

JOIN-Anweisungen

In einer traditionellen RDBMS SQL-Implementierung können Zeilen von separaten Tabellen über verbundene Spalten mithilfe von JOIN-Anweisungen in einer einzelnen tabellarischen Antwort kombiniert werden. Dies ermöglicht die relationale Datenmodellierung und stellt im Vergleich zu den systemintern in Elasticsearch verfügbaren Optionen, mit denen dies erreicht werden kann, ein wesentliches Thema dar. Elasticsearch SQL bietet derzeit keinen JOIN-Operator an, sondern erlaubt es den Anwendern, geschachtelte Dokumente zu nutzen, die eine einfache relationale 1:n-Modellierung ermöglichen. Die Abfrage geschachtelter Dokumente wird für den Anwender transparent gehandhabt. Die Funktionalität können wir nur mithilfe eines Index veranschaulichen, der Daten dieser Art enthält. In diesem Beispiel haben wir daher einen „Bestellungsindex auf demo.elastic.co geladen. Die Dokumente dieses Index stellen Bestellungen einer eCommerce-Site dar und enthalten Felder wie beispielsweise Bestelldatum (order_date), Ort der Rechnungsstellung (billing_city) und Nachname des Kunden (customer_last_name). Darüber hinaus enthält das Feld „Produkte“ (products) für jedes Produkt in der Bestellung ein geschachteltes Unterdokument. Beispiel:

{
          "billing_last_name": "Green",
          "billing_first_name": "Jason",
          "order_id": 519894,
          "products": [
            {
              "tax_amount": 0,
              "taxful_price": 22.99,
              "quantity": 1,
              "taxless_price": 22.99,
              "discount_amount": 0,
              "base_unit_price": 22.99,
              "discount_percentage": 0,
              "product_name": "Briefcase - black",
              "manufacturer": "Pier One",
              "min_price": 11.27,
              "created_on": "2016-11-08T04:16:19+00:00",
              "unit_discount_amount": 0,
              "price": 22.99,
              "product_id": 12733,
              "base_price": 22.99,
              "_id": "sold_product_519894_12733",
              "category": "Men's Accessories",
              "sku": "PI952HA0M-Q11"
            },
            {
              "tax_amount": 0,
              "taxful_price": 16.99,
              "quantity": 1,
              "taxless_price": 16.99,
              "discount_amount": 0,
              "base_unit_price": 16.99,
              "discount_percentage": 0,
              "product_name": "3 PACK - Boxer shorts - white/navy",
              "manufacturer": "Pier One",
              "min_price": 8.33,
              "created_on": "2016-11-08T04:16:19+00:00",
              "unit_discount_amount": 0,
              "price": 16.99,
              "product_id": 18370,
              "base_price": 16.99,
              "_id": "sold_product_519894_18370",
              "category": "Men's Clothing",
              "sku": "PI982AA0Y-A11"
            }
          ],
          "has_error": false,
          "customer_last_name": "Green",
          "currency": "EUR",
          "billing_first_name": "Jason",
          "shipping_country_code": "US",
          "email": "swagelastic@gmail.com",
          "day_of_week": "Tuesday",
          "geoip": {
            "continent_name": "North America",
            "city_name": "New York",
            "country_iso_code": "US",
            "location": {
              "lon": -73.9862,
              "lat": 40.7662
            },
            "region_name": "New York"
          },
          "payment_status": "FULLY_PAID",
          ...
}

Normalerweise müssten Anwender zur Abfrage dieser Dokumente verstehen, warum für das Feld „Produkte“ (products) ein geschachtelter Datentyp verwendet wird, und über Grundkenntnisse der Syntax von geschachtelten Abfragen verfügen. Doch mit Elasticsearch SQL können wir diese geschachtelten Dokumente abfragen, als würde jedes von ihnen eine separate Zeile mit Feldern ihres übergeordneten Dokuments darstellen (d. h., faktisch vereinfachen wir die Struktur für die Präsentation). Betrachten Sie die oben angegebene Bestellung, die zwei Produkte umfasst. Wenn Felder von den untergeordneten Dokumenten des Produkts angefordert werden, besteht das Ergebnis der Abfrage aus zwei Zeilen. Jede Zeile kann bei Anforderung ebenfalls Felder der übergeordneten Bestellung enthalten. Beispiel:

„Finde Flüge, die der Rechnungsname genommen hat, sowie die gekauften Produkte für Bestellnummer 518894.“

sql> SELECT billing_last_name, billing_first_name, products.price, products.product_id FROM orders WHERE order_id=519894;
billing_last_name|billing_first_name|products.price |products.product_id
-----------------+------------------+---------------+-------------------
Green            |Jason             |16.984375      |18370
Green            |Jason             |22.984375      |12733

Probieren Sie es auf demo.elastic.co aus.

Die _translate-API zeigt, wie diese Abfrage mithilfe einer geschachtelten Abfrage erstellt wurde:

{
  "size": 1000,
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "order_id": {
              "value": 519894,
              "boost": 1
            }
          }
        },
        {
          "nested": {
            "query": {
              "match_all": {
                "boost": 1
              }
            },
            "path": "products",
            "ignore_unmapped": false,
            "score_mode": "none",
            "boost": 1,
            "inner_hits": {
              "ignore_unmapped": false,
              "from": 0,
              "size": 99,
              "version": false,
              "explain": false,
              "track_scores": false,
              "_source": false,
              "stored_fields": "_none_",
              "docvalue_fields": [
                "products.product_id",
                "products.price"
              ]
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  },
  "_source": {
    "includes": [
      "billing_last_name",
      "billing_first_name"
    ],
    "excludes": []
  },
  "sort": [
    {
      "_doc": {
        "order": "asc"
      }
    }
  ]
}

Probieren Sie es auf demo.elastic.co aus.

Hätten wir dagegen nur übergeordnete Felder abgefragt, wäre uns nur eine Zeile angezeigt worden:

„Finde Flüge, die der Rechnungsname genommen hat, für Bestellnummer 518894.“

sql> SELECT billing_last_name, billing_first_name FROM orders WHERE order_id=519894;
billing_last_name|billing_first_name
-----------------+------------------
Green            |Jason

Probieren Sie es auf demo.elastic.co aus.

Derzeitige Einschränkungen und zukünftige Erweiterungen ...

Beim Experimentieren mit dem Produkt können Sie schon frühzeitig auf folgende Einschränkungen stoßen:

  • Kreuztabellen-/Indexabfragen: Dies ist unter der Voraussetzung möglich, dass die Mappings der Indizes identisch sind. Selbst kleinste Unterschiede führen in der Abfragezeit zu einem Fehler.
  • JOIN-Anweisungen; Wie zuvor dargelegt, unterstützen wir JOIN-Anweisungen nur im begrenzten Maße durch Verwendung geschachtelter Dokumente.
  • Sortierung von Gruppen mithilfe von GROUP BY: Wie zuvor dargelegt, wurde diese Einschränkung aus der verbundenen Aggregation von Elasticsearch übernommen.
  • Geschachtelte SELECT-Klauseln: Dies sind gängige Methoden zum Drilldown auf BI-Tools (Business Intelligence-Tools). Während geschachtelte SELECT-Anweisungen unter Verwendung mehrerer Indizes einer JOIN-Anweisung entsprechen würden, könnten Anweisungen, die den gleichen Index verwenden, neu geschrieben und ausgeführt werden. Dies könnten wir möglicherweise in der Zukunft umsetzen.

Zu den Vorteilen von Elasticsearch, deren Umsetzung wir für zukünftige Releases geplant haben, gehören:

Vielen Dank für Ihre Aufmerksamkeit! Wir würden uns freuen, Sie auch bei den folgenden Lektionen der Reihe Einführung in Elasticsearch SQL begrüßen zu können.