<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Craig Taverner - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Craig Taverner - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/de/search-labs/author/craig-taverner</link>
    </image>
    <link>https://www.elastic.co/de/search-labs/author/craig-taverner</link>
    <atom:link href="https://www.elastic.co/de/search-labs/rss/author/craig-taverner.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[de]]></language>
    <lastBuildDate>Sun, 11 Oct 2026 17:53:06 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Geodaten mit Kibana in Elasticsearch einlesen und in ES|QL verwenden]]></title>
    <description><![CDATA[Wie man Kibana und den CSV-Ingest-Prozessor verwendet, um Geodaten in Elasticsearch einzulesen und damit in der Elasticsearch Query Language (ES|QL) zu suchen. Elasticsearch verfügt über leistungsstarke Geodaten-Suchfunktionen, die nun in ES|QL integriert werden, um die Benutzerfreundlichkeit und OGC-Vertrautheit deutlich zu verbessern. Um diese Funktionen nutzen zu können, benötigen wir jedoch Geodaten.]]></description>
    <content:encoded><![CDATA[<p>Kürzlich haben wir einen Blogbeitrag veröffentlicht, in dem wir die Verwendung der neuen <a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one">Geodaten-Suchfunktionen</a> <a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one">in</a> <a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one">ES|QL</a>, der neuen, leistungsstarken <a href="https://www.elastic.co/search-labs/blog/esql-piped-query-language-goes-ga">Abfragesprache</a> von Elasticsearch, beschreiben. Um diese Funktionen nutzen zu können, benötigen Sie Geodaten in Elasticsearch. In diesem Blogbeitrag zeigen wir Ihnen, wie Sie Geodaten einlesen und in ES|QL-Abfragen verwenden.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfc041ebca11476c6/6a16f70560084b31b93c4344/01fde3b1d714f12bf8673140c9f2f940d443de31-1440x823.jpg" alt="ESQL-Geodatensuche" /><h2>Importieren von Geodaten mit Kibana</h2><p>Die Daten, die wir für die Beispiele im vorherigen Blog verwendet haben, basierten auf Daten, die wir intern für Integrationstests verwenden. Zu Ihrer Bequemlichkeit haben wir es hier in Form einiger CSV-Dateien beigefügt, die Sie problemlos mit Kibana importieren können. Die Daten setzen sich aus Flughäfen, Städten und Stadtgrenzen zusammen. Sie können die Daten hier herunterladen:</p><ul><li><p><a href="https://raw.githubusercontent.com/elastic/elasticsearch-labs/refs/heads/main/supporting-blog-content/geospatial-data-ingest/airports/airports.csv">airports.csv</a></p><ul><li><p>Dies beinhaltet die Zusammenführung von drei Datensätzen:</p><ul><li><p>Flughäfen (Namen, Standorte und zugehörige Daten) von <a href="https://www.naturalearthdata.com/downloads/10m-cultural-vectors/airports/">Natural Earth</a></p></li><li><p>Stadtstandorte von <a href="https://simplemaps.com/data/world-cities">SimpleMaps</a></p></li><li><p>Flughafenhöhen aus <a href="https://www.partow.net/miscellaneous/airportdatabase/">der globalen Flughafendatenbank</a></p></li></ul></li></ul></li><li><p><a href="https://raw.githubusercontent.com/elastic/elasticsearch-labs/refs/heads/main/supporting-blog-content/geospatial-data-ingest/airports/airport_city_boundaries.csv">airport_city_boundaries.csv</a></p><ul><li><p>Dies beinhaltet eine Zusammenführung der oben genannten Flughafen- und Städtenamen mit einer neuen Quelle:</p><ul><li><p>Stadtgrenzen aus <a href="https://www.openstreetmap.org/">OpenStreetMap</a></p></li></ul></li></ul></li></ul><p>Wie Sie sich vorstellen können, haben wir einige Zeit damit verbracht, diese Datenquellen in den beiden oben genannten Dateien zusammenzuführen, mit dem Ziel, die Geodatenfunktionen von ES|QL testen zu können. Dies entspricht möglicherweise nicht ganz Ihren spezifischen Datenanforderungen, aber hoffentlich gibt Ihnen dies eine Vorstellung davon, was möglich ist. Insbesondere möchten wir einige interessante Dinge demonstrieren:</p><ul><li><p>Importieren von Daten mit Geodatenfeldern zusammen mit anderen indexierbaren Daten</p></li><li><p>Importieren von <code>geo_point</code> und <code>geo_shape</code> -Daten und deren gemeinsame Verwendung in Abfragen</p></li><li><p>Importieren von Daten in zwei Indizes, die über eine räumliche Beziehung verknüpft werden können</p></li><li><p>Erstellung einer Ingest-Pipeline zur Erleichterung zukünftiger Importe (über Kibana hinaus)</p></li><li><p>Einige Beispiele für Ingest-Prozessoren, wie <code>csv</code>, <code>convert</code> und <code>split</code></p></li></ul><p>In diesem Blogbeitrag geht es zwar um die Arbeit mit CSV-Daten, aber es ist wichtig zu verstehen, dass es <a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html">mehrere Möglichkeiten</a> <a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html"></a> <a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html">gibt, Geodaten mit</a> <a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html">Kibana</a> hinzuzufügen . Innerhalb der Kartenanwendung können Sie durch Trennzeichen getrennte Daten wie CSV, GeoJSON und ESRI ShapeFiles hochladen und auch direkt in der Karte Formen zeichnen. In diesem Blogbeitrag konzentrieren wir uns auf den Import von CSV-Dateien von der Kibana-Startseite.</p><h3>Import der Flughäfen</h3><p>Die erste Datei, <a href="https://raw.githubusercontent.com/elastic/elasticsearch-labs/refs/heads/main/supporting-blog-content/geospatial-data-ingest/airports/airports.csv">airports.csv</a>, hat einige interessante Eigenheiten, mit denen wir uns auseinandersetzen müssen. Erstens weisen die Spalten zusätzliche Leerzeichen als Trennzeichen auf, was für CSV-Dateien untypisch ist. Zweitens handelt es sich bei dem Feld <code>type</code> um ein Mehrwertfeld, das wir in separate Felder aufteilen müssen. Schließlich handelt es sich bei einigen Feldern nicht um Zeichenketten, sondern um Felder, die in den richtigen Datentyp konvertiert werden müssen. All dies kann mithilfe der CSV-Importfunktion von Kibana erfolgen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt393bc416bf425301/6a16f707839dfa1e86dcfca9/b1afd8c95973bec32f229a9adfaef14680b09a8e-1944x478.png" alt="Kibana Upload – Vorschau" /><p>Beginnen Sie auf der Kibana-Startseite. Es gibt einen Abschnitt mit dem Titel „Erste Schritte durch Hinzufügen von Integrationen“, der einen Link mit der Bezeichnung „Datei hochladen“ enthält:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte12fc741edab20d3/6a16f709acf088600fbe98bf/996372bb3a52859cc840bd1d8f984a33a0e7ada3-1180x410.png" alt="Kibana-Startseite – Datei hochladen" /><p>Klicken Sie auf diesen Link, und Sie gelangen zur Seite „Datei hochladen“. Hier können Sie die <code>airports.csv</code> -Datei per Drag &amp; Drop einfügen. Kibana analysiert die Datei und zeigt Ihnen eine Vorschau der Daten an. Das System hätte das Trennzeichen automatisch als Komma und die erste Zeile als Kopfzeile erkennen sollen. Allerdings wurden vermutlich weder die zusätzlichen Leerzeichen zwischen den Spalten entfernt, noch wurden die Typen der Felder bestimmt, da angenommen wurde, dass alle Felder entweder <code>text</code> oder <code>keyword</code> sind. Das müssen wir beheben.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf65a09ec0c7a61ad/6a16f70ad7c0227aedde626f/1d9ffa6cdbc0d67a228be1a747ec1ebda6a63099-1800x538.png" alt="Kibana Upload – Vorschau" /><p>Klicken Sie auf <code>Override settings</code> und aktivieren Sie das Kontrollkästchen für <code>Should trim fields</code>, und anschließend <code>Apply</code> um die Einstellungen zu schließen. Nun müssen wir die Datentypen der Felder korrigieren. Dies ist auf der nächsten Seite verfügbar, also klicken Sie bitte auf <code>Import</code>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltda9a5f85d8e693dc/6a16f70c60084b72f53c4348/a97aceffb1858eae26a213336913505ae9923b03-1800x526.png" alt="Kibana Upload - Import" /><p>Wählen Sie zuerst einen Indexnamen aus und anschließend <code>Advanced</code> , um zur Seite für Feldzuordnungen und Datenverarbeitung zu gelangen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt56705083cdd9eb18/6a16f70d66c4f93350f8bdbb/058b0fb09da0b8d7f9c9b0a9c83b8b485ce43925-1440x629.png" alt="Kibana Upload – Feldzuordnungen" /><p>Hier müssen wir sowohl die Feldzuordnungen für den Index als auch die Datenaufnahmepipeline anpassen. Erstens hat Kibana wahrscheinlich das Feld <code>scalerank</code> automatisch als <code>long</code> erkannt, aber die Felder <code>location</code> und <code>city_location</code> fälschlicherweise als <code>keyword</code> interpretiert. Ändern Sie sie in <code>geo_point</code>, sodass die Zuordnungen am Ende etwa so aussehen:</p>{
  "properties": {
    "abbrev":        { "type": "keyword" },
    "city":          { "type": "keyword" },
    "city_location": { "type": "geo_point" },
    "country":       { "type": "keyword" },
    "elevation":     { "type": "double" },
    "location":      { "type": "geo_point" },
    "name":          { "type": "text" },
    "scalerank":     { "type": "long" },
    "type":          { "type": "keyword" }
  }
}<p>Sie haben hier eine gewisse Flexibilität, aber beachten Sie, dass die Wahl des Typs Einfluss darauf hat, wie das Feld indiziert wird und welche Art von Abfragen möglich ist. Wenn Sie beispielsweise <code>location</code> auf <code>keyword</code> belassen, können Sie keine Geodaten-Suchanfragen darauf durchführen. Wenn Sie <code>elevation</code> als <code>text</code> belassen, können Sie keine numerischen Bereichsabfragen darauf durchführen.</p><p>Jetzt ist es an der Zeit, die Datenaufnahmepipeline zu reparieren. Falls Kibana <code>scalerank</code> automatisch als <code>long</code> erkannt hat, wurde außerdem ein Prozessor hinzugefügt, um das Feld in <code>long</code> umzuwandeln. Wir müssen einen ähnlichen Prozessor für das Feld <code>elevation</code> hinzufügen, der es diesmal in <code>double</code> umwandelt. Bearbeiten Sie die Pipeline, um sicherzustellen, dass diese Konvertierung vorhanden ist. Bevor wir dies speichern, möchten wir noch eine weitere Konvertierung durchführen, um das Feld <code>type</code> in mehrere Felder aufzuteilen. Fügen Sie der Pipeline einen <code>split</code> -Prozessor mit folgender Konfiguration hinzu:</p>{
  "split": {
    "field": "type",
    "separator": ":",
    "ignore_missing": true
  }
}<p>Die finale Datenaufnahmepipeline sollte wie folgt aussehen:</p>{
  "description": "Ingest pipeline created by text structure finder",
  "processors": [
    {
      "csv": {
        "field": "message",
        "target_fields": [
          "abbrev",
          "name",
          "scalerank",
          "type",
          "location",
          "country",
          "city",
          "city_location",
          "elevation"
        ],
        "ignore_missing": false,
        "trim": true
      }
    },
    {
      "convert": {
        "field": "scalerank",
        "type": "long",
        "ignore_missing": true
      }
    },
    {
      "convert": {
        "field": "elevation",
        "type": "double",
        "ignore_missing": true
      }
    },
    {
      "split": {
        "field": "type",
        "separator": ":",
        "ignore_missing": true
      }
    },
    {
      "remove": {
        "field": "message"
      }
    }
  ]
}<p>Beachten Sie, dass wir keinen Konvertierungsprozessor für die Felder <code>location</code> und <code>city_location</code> hinzugefügt haben. Dies liegt daran, dass der Typ <code>geo_point</code> in der Feldzuordnung das WKT- Format der Daten in diesen Feldern bereits versteht. Der Typ <code>geo_point</code> versteht eine Reihe von Formaten, darunter <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-point.html">WKT, GeoJSON und mehr</a>. Wenn wir beispielsweise zwei Spalten in der CSV-Datei für <code>latitude</code> und <code>longitude</code> hätten, hätten wir entweder einen <code>script</code> oder einen <code>set</code> Prozessor hinzufügen müssen, um diese zu einem einzigen <code>geo_point</code> Feld zu kombinieren (z. B. <code>"set": {"field": "location", "value": "{{lat}},{{lon}}"}</code>).</p><p>Wir sind nun bereit, die Datei zu importieren. Klicken Sie auf <code>Import</code> , und die Daten werden mit den soeben definierten Mappings und der Ingest-Pipeline in den Index importiert. Sollten beim Einlesen der Daten Fehler auftreten, werden diese von Kibana hier gemeldet, sodass Sie entweder die Quelldaten oder die Einlesepipeline bearbeiten und es erneut versuchen können.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte81621425c7289c5/6a16f70f839dfaf608dcfcad/55dde2940c7aba66ce8257d15007ef797b8a5107-1440x415.png" alt="Kibana Upload - Importieren" /><p>Beachten Sie, dass eine neue Aufnahmepipeline erstellt wurde. Dies kann angezeigt werden, indem man im Kibana-Bereich <code>Stack Management</code> auf die Option <code>Ingest pipelines</code> klickt. Hier können Sie die soeben erstellte Pipeline sehen und sie bei Bedarf bearbeiten. Tatsächlich kann der Abschnitt <code>Ingest pipelines</code> zum Erstellen und Testen von Ingest-Pipelines verwendet werden, eine sehr nützliche Funktion, wenn Sie noch komplexere Ingests planen.</p><p>Wenn Sie diese Daten sofort erkunden möchten, springen Sie zu den späteren Abschnitten. Wenn Sie aber auch die Stadtgrenzen importieren möchten, lesen Sie weiter.</p><h3>Importieren der Stadtgrenzen</h3><p>Die unter <a href="https://raw.githubusercontent.com/elastic/elasticsearch-labs/refs/heads/main/supporting-blog-content/geospatial-data-ingest/airports/airport_city_boundaries.csv">airport_city_boundaries.csv</a> verfügbare Datei mit den Stadtgrenzen ist etwas einfacher zu importieren als das vorherige Beispiel. Es enthält ein <code>city_boundary</code> Feld, das eine WKT-Darstellung der Stadtgrenze als <code>POLYGON</code> ist, und ein <code>city_location</code> Feld, das eine <code>geo_point</code> Darstellung des Stadtstandorts ist. Wir können diese Daten auf ähnliche Weise wie die Flughafendaten importieren, allerdings mit einigen Unterschieden:</p><ul><li><p>Wir mussten die Überschreibungseinstellung <code>Has header row</code> auswählen, da diese nicht automatisch erkannt wurde.</p></li><li><p>Wir mussten keine Felder kürzen, da die Daten bereits frei von überflüssigen Leerzeichen waren.</p></li><li><p>Wir mussten die Datenaufnahmepipeline nicht bearbeiten, da alle Datentypen entweder Zeichenketten oder räumliche Datentypen waren.</p></li><li><p>Wir mussten jedoch die Feldzuordnungen bearbeiten, um das Feld <code>city_boundary</code> auf <code>geo_shape</code> und das Feld <code>city_location</code> auf  zu setzen. <code>geo_point</code></p></li></ul><p>Unsere endgültigen Feldzuordnungen sahen wie folgt aus:</p>{
  "properties": {
    "abbrev":        { "type": "keyword" },
    "airport":       { "type": "keyword" },
    "city":          { "type": "keyword" },
    "city_boundary": { "type": "geo_shape" },
    "city_location": { "type": "geo_point" },
    "region":        { "type": "text" }
  }
}<p>Wie beim Import mit <code>airports.csv</code> zuvor, klicken Sie einfach auf <code>Import</code> , um die Daten in den Index zu importieren. Die Daten werden mit den von uns bearbeiteten Mappings und der von Kibana definierten Ingest-Pipeline importiert.</p><h3>Erkundung von Geodaten mit Entwicklerwerkzeugen</h3><p>In Kibana ist es üblich, die indizierten Daten mit dem Befehl „Discover“ zu erkunden. Wenn Sie jedoch Ihre eigene Anwendung mit ES|QL-Abfragen schreiben möchten, könnte es interessanter sein, auf die reine Elasticsearch-API zuzugreifen. Kibana verfügt über eine komfortable Konsole zum Experimentieren mit dem Schreiben von Abfragen. Dies wird als <code>Dev Tools</code> -Konsole bezeichnet und befindet sich in der Kibana-Seitenleiste. Diese Konsole kommuniziert direkt mit dem Elasticsearch-Cluster und kann zum Ausführen von Abfragen, Erstellen von Indizes und vielem mehr verwendet werden.</p><p>Versuchen Sie Folgendes:</p>POST /_query?error_trace=true&amp;format=txt
{
  "query": """
FROM airports
| EVAL distance = ST_DISTANCE(city_location, TO_GEOPOINT("POINT(12.565 55.673)"))
| WHERE distance &lt; 1000000 AND scalerank &lt; 6 AND distance &gt; 10000
| SORT distance ASC
| KEEP distance, abbrev, name, location, country, city, elevation
| LIMIT 10
  """
}<p>Dies sollte folgende Ergebnisse liefern:</p><p>Distanz</p><p>Abkürzung</p><p>Name</p><p>Ort</p><p>Land</p><p>Stadt</p><p>Elevation</p><p>273418.05776847183</p><p>SCHINKEN</p><p>Hamburg</p><p>PUNKT (10.005647830925 53.6320011640866)</p><p>Deutschland</p><p>Norderstedt</p><p>17.0</p><p>337534.653466062</p><p>TXL</p><p>Berlin-Tegel Int'l</p><p>PUNKT (13.2903090925074 52.5544287044101)</p><p>Deutschland</p><p>Hohen Neuendorf</p><p>38,0</p><p>483713.15032266214</p><p>OSL</p><p>Oslo Gardermoen</p><p>Punkt (11.0991032762581 60.1935783171386)</p><p>Norwegen</p><p>Oslo</p><p>208.0</p><p>522538.03148094116</p><p>BMA</p><p>Bromma</p><p>PUNKT (17.9456175406145 59.3555902065112)</p><p>Schweden</p><p>Stockholm</p><p>15.0</p><p>522538.03148094116</p><p>ARN</p><p>Arlanda</p><p>Punkt (17.9307299016916 59.6511203397372)</p><p>Schweden</p><p>Stockholm</p><p>38,0</p><p>624274.8274399083</p><p>DUS</p><p>Düsseldorf Int'l</p><p>PUNKT (6,76494446612174 51,2781820420774)</p><p>Deutschland</p><p>Düsseldorf</p><p>45,0</p><p>633388.6966435644</p><p>PRG</p><p>Ruzyn</p><p>PUNKT (14.2674849854076 50.1076511703671)</p><p>Tschechien</p><p>Prag</p><p>381,0</p><p>635911.1873311149</p><p>AMS</p><p>Schiphol</p><p>Punkt (4,76437693232812 52,3089323889822)</p><p>Niederlande</p><p>Hoofddorp</p><p>-3.0</p><p>670864.137958866</p><p>FRA</p><p>Frankfurt International</p><p>PUNKT (8.57182286907608 50.0506770895207)</p><p>Deutschland</p><p>Frankfurt</p><p>111,0</p><p>683239.2529970079</p><p>WAW</p><p>Okecie Int'l</p><p>Punkt (20.9727263383587 52.171026749259)</p><p>Polen</p><p>Piaseczno</p><p>111,0</p><h2>Visualisierung von Geodaten mit Kibana Maps</h2><p>Kibana Maps ist ein leistungsstarkes Werkzeug zur Visualisierung von Geodaten. Es kann verwendet werden, um Karten mit mehreren Ebenen zu erstellen, wobei jede Ebene einen anderen Datensatz darstellt. Die Daten können auf verschiedene Weise gefiltert, aggregiert und formatiert werden. In diesem Abschnitt zeigen wir Ihnen, wie Sie in Kibana Maps eine Karte mit den Daten erstellen, die wir im vorherigen Abschnitt importiert haben.</p><p>Navigieren Sie im Kibana-Menü zu <code>Analytics</code>-&gt;<code>Maps</code> , um eine neue Kartenansicht zu öffnen. Klicken Sie auf <code>Add Layer</code> und wählen Sie <code>Documents</code> aus, wählen Sie die Datenansicht <code>airports</code> und bearbeiten Sie dann den Ebenenstil, um die Markierungen mithilfe des Feldes <code>elevation</code> einzufärben, damit wir leicht erkennen können, wie hoch jeder Flughafen liegt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdcc4736d88c1abc9/6a16f7102b835f7353f4afca/9e63726d7c059331e6e20e474f8abee53dc2cbb4-840x388.png" alt="Kibana Maps – Flughafen-Layer-Stil" /><p>Klicken Sie auf „Änderungen beibehalten“, um die Karte zu speichern:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ec3cc535b5c21d8/6a16f71375879ec091fe15dc/32ad1dadb5d341a2b66662c58638b781122fc22c-2852x1528.png" alt="Kibana Maps – Flughäfen" /><p>Fügen Sie nun eine zweite Ebene hinzu und wählen Sie diesmal die Datenansicht <code>airport_city_boundaries</code> aus. Dieses Mal verwenden wir das Feld <code>city_boundary</code> , um die Ebene zu gestalten, und stellen die Füllfarbe auf ein helles Blau ein. Dadurch werden die Stadtgrenzen auf der Karte angezeigt. Achten Sie darauf, die Ebenen neu anzuordnen, damit die Flughafenmarkierungen ganz oben liegen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2932d7ff4a7206c9/6a16f7156f7f0409f09145c7/53dd65026f9a98c13f2cc4f9328a79242f0b70de-2854x1510.png" alt="Kibana Maps – Layerstil für Stadtgrenzen" /><h2>Räumliche Verknüpfungen</h2><p>ES|QL unterstützt keine <code>JOIN</code> -Befehle, aber mit dem <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-commands.html#esql-enrich"><code>ENRICH</code></a> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-commands.html#esql-enrich">-Befehl</a> lässt sich ein Sonderfall eines Joins realisieren. Dieser Befehl funktioniert ähnlich wie ein „Left Join“ in SQL und ermöglicht es Ihnen, Ergebnisse aus einem Index mit Daten aus einem anderen Index anzureichern, basierend auf einer räumlichen Beziehung zwischen den beiden Datensätzen.</p><p>Nehmen wir beispielsweise an, wir reichern die Ergebnisse einer Tabelle mit Flughäfen um zusätzliche Informationen über die jeweilige Stadt an, indem wir die Stadtgrenze ermitteln, die den Flughafenstandort enthält, und führen dann einige statistische Auswertungen der Ergebnisse durch:</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary
| STATS
    centroid = ST_CENTROID_AGG(location),
    count = COUNT(city_location)
    BY region
| SORT count DESC
| LIMIT 10<p>Wenn Sie diese Abfrage ausführen, ohne vorher den Anreicherungsindex vorzubereiten, erhalten Sie eine Fehlermeldung wie:</p>cannot find enrich policy [city_boundaries]<p>Dies liegt daran, dass ES|QL, wie bereits erwähnt, keine echten <code>JOIN</code> -Befehle unterstützt. Ein wichtiger Grund dafür ist, dass Elasticsearch ein verteiltes System ist und Joins aufwändige Operationen sind, die schwer zu skalieren sind. Der Befehl <code>ENRICH</code> kann jedoch sehr effizient sein, da er speziell vorbereitete Anreicherungsindizes nutzt, die im gesamten Cluster dupliziert werden, wodurch lokale Joins auf jedem Knoten durchgeführt werden können.</p><p>Um dies besser zu verstehen, konzentrieren wir uns auf den Befehl <code>ENRICH</code> in der obigen Abfrage:</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary<p>Dieser Befehl weist Elasticsearch an, die aus dem Index <code>airports</code> abgerufenen Ergebnisse anzureichern und einen Join <code>intersects</code> zwischen dem Feld <code>city_location</code> des ursprünglichen Index und dem Feld <code>city_boundary</code> des Index <code>airport_city_boundaries</code> durchzuführen, den wir bereits in einigen Beispielen verwendet haben. Einige dieser Informationen sind in dieser Abfrage jedoch nicht klar ersichtlich. Was wir sehen, ist der Name einer Anreicherungsrichtlinie <code>city_boundaries</code>, und die fehlenden Informationen sind in dieser Richtliniendefinition enthalten.</p>{
  "geo_match": {
    "indices": "airport_city_boundaries",
    "match_field": "city_boundary",
    "enrich_fields": ["city", "airport", "region", "city_boundary"]
  }
}<p>Hier sehen wir, dass eine <code>geo_match</code> -Abfrage durchgeführt wird (<code>intersects</code> ist der Standardwert), das Feld, mit dem abgeglichen werden soll, ist <code>city_boundary</code>, und die <code>enrich_fields</code> sind die Felder, die wir dem Originaldokument hinzufügen möchten. Eines dieser Felder, nämlich <code>region</code> wurde tatsächlich als Gruppierungsschlüssel für den Befehl <code>STATS</code> verwendet, was ohne diese 'left join'-Funktion nicht möglich gewesen wäre. Weitere Informationen zu Anreicherungsrichtlinien finden Sie in der <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-setup.html">Anreicherungsdokumentation</a>.</p><p>Die Anreicherungsindizes und -richtlinien in Elasticsearch wurden ursprünglich für die Anreicherung von Daten während der Indexierung entwickelt, wobei Daten aus einem anderen vorbereiteten Anreicherungsindex verwendet wurden. In ES|QL hingegen funktioniert der Befehl <code>ENRICH</code> zur Abfragezeit und erfordert keine Verwendung von Ingest-Pipelines. Dadurch ähnelt es im Prinzip einem SQL <code>LEFT JOIN</code>, nur dass man nicht beliebige zwei Indizes verknüpfen kann, sondern nur einen normalen Index auf der linken Seite mit einem speziell vorbereiteten Anreicherungsindex auf der rechten Seite.</p><p>In beiden Fällen, ob für Ingest-Pipelines oder die Verwendung in ES|QL, müssen einige vorbereitende Schritte durchgeführt werden, um den Anreicherungsindex und die Richtlinie einzurichten. Wir haben den Index <code>airport_city_boundaries</code> bereits oben importiert, dieser kann jedoch nicht direkt als Anreicherungsindex im Befehl <code>ENRICH</code> verwendet werden. Zunächst müssen wir zwei Schritte durchführen:</p><ul><li><p>Erstellen Sie die oben beschriebene Anreicherungsrichtlinie, um den Quellindex, das Feld im Quellindex, mit dem abgeglichen werden soll, und die Felder, die nach dem Abgleich zurückgegeben werden sollen, zu definieren.</p></li><li><p>Führen Sie diese Richtlinie aus, um den Anreicherungsindex zu erstellen. Dabei wird ein spezieller interner Index erstellt, indem der ursprüngliche Quellindex in eine effizientere Datenstruktur eingelesen und anschließend im gesamten Cluster kopiert wird.</p></li></ul><p>Die Anreicherungsrichtlinie kann mit folgendem Befehl erstellt werden:</p>PUT /_enrich/policy/city_boundaries
{
  "match": {
    "indices": "airport_city_boundaries",
    "match_field": "city_boundary",
    "enrich_fields": ["city", "airport", "region", "city_boundary"]
  }
}<p>Die Richtlinie kann mit folgendem Befehl ausgeführt werden:</p>POST /_enrich/policy/city_boundaries/_execute<p>Beachten Sie, dass Sie diese Richtlinie erneut ausführen müssen, wenn Sie den Inhalt des Index <code>airport_city_boundaries</code> ändern, damit die Änderungen im Anreicherungsindex sichtbar werden. Führen wir nun die ursprüngliche ES|QL-Abfrage erneut aus:</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary
| STATS
    centroid = ST_CENTROID_AGG(location),
    count = COUNT(city_location)
    BY region
| SORT count DESC
| LIMIT 10<p>Dies liefert die Top 5 Regionen mit den meisten Flughäfen, zusammen mit dem Schwerpunkt aller Flughäfen, die übereinstimmenden Regionen zugeordnet sind, und der Längenspanne der WKT-Darstellung der Stadtgrenzen innerhalb dieser Regionen:</p><p>Schwerpunkt</p><p>Anzahl</p><p>Region</p><p>PUNKT (-12.139086859300733 31.024386116624648)</p><p>126</p><p>null</p><p>PUNKT (-83.10398317873478 42.300230911932886)</p><p>3</p><p>Detroit</p><p>Punkt (39.74537850357592 47.21613017376512)</p><p>3</p><p>городской округ Батайск</p><p>PUNKT (-156.80986787192523 20,476673701778054)</p><p>3</p><p>Hawaii</p><p>PUNKT (-73.94515332765877 40.70366442203522)</p><p>3</p><p>Stadt New York</p><p>PUNKT (-83.10398317873478 42.300230911932886)</p><p>3</p><p>Detroit</p><p>PUNKT (-76.66873019188643 24.306286952923983)</p><p>2</p><p>New Providence</p><p>PUNKT (-3,0252167768776417 51,39245774131268)</p><p>2</p><p>Cardiff</p><p>PUNKT (-115.40993484668434 32,73126147687435)</p><p>2</p><p>Municipio de Mexicali</p><p>Punkt (41.790108773857355 50.302146775648)</p><p>2</p><p>Zentralbezirk</p><p>PUNKT (-73.88902732171118 45.57078813901171)</p><p>2</p><p>Montréal</p><p>Möglicherweise stellen Sie auch fest, dass die am häufigsten vorkommende Region <code>null</code> war. Was könnte das bedeuten? Zur Erinnerung: Ich habe diesen Befehl mit einem 'Left Join' in SQL verglichen. Das bedeutet, dass, wenn keine übereinstimmende Stadtgrenze für einen Flughafen gefunden wird, der Flughafen trotzdem zurückgegeben wird, jedoch mit <code>null</code> Werten für die Felder ab dem <code>airport_city_boundaries</code> Index. Es stellte sich heraus, dass es 125 Flughäfen gab, bei denen kein passender Eintrag <code>city_boundary</code> gefunden wurde, und einen Flughafen mit einer Übereinstimmung, bei dem das Feld <code>region</code> den <code>null</code> hatte. Dies führte zu einer Zählung von 126 Flughäfen ohne <code>region</code> in den Ergebnissen. Falls Ihr Anwendungsfall erfordert, dass alle Flughäfen einer Stadtgrenze zugeordnet werden können, müssten zusätzliche Daten beschafft werden, um die Lücken zu schließen. Es wäre notwendig, zwei Dinge zu ermitteln:</p><ul><li><p>Welche Datensätze im Index <code>airport_city_boundaries</code> haben keine <code>city_boundary</code> Felder?</p></li><li><p>welche Datensätze im Index <code>airports</code> nicht mit dem Befehl <code>ENRICH</code> übereinstimmen (d.h. (überschneiden sich nicht)</p></li></ul><h2>Verwendung von ES|QL für Geodaten in Kibana Maps</h2><p>Kibana hat die Unterstützung für Spatial ES|QL in der Kartenanwendung hinzugefügt. Das bedeutet, dass Sie nun ES|QL verwenden können, um in Elasticsearch nach Geodaten zu suchen und die Ergebnisse auf einer Karte zu visualisieren.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt91922eb4ef43d290/6a16f7161949f737bfe7a7b5/bd78470bd8a4bc60f0db7006bd804b8fe87e2fea-1440x683.png" alt="Kibana Layers ES|QL" /><p>Im Menü „Ebenen hinzufügen“ gibt es eine neue Ebenenoption mit der Bezeichnung „ES|QL“. Wie alle bisher beschriebenen Geodatenfunktionen befindet sich auch diese in der „technischen Vorschauphase“. Durch Auswahl dieser Option können Sie der Karte eine Ebene hinzufügen, die auf den Ergebnissen einer ES|QL-Abfrage basiert. Man könnte beispielsweise eine Ebene zur Karte hinzufügen, die alle Flughäfen der Welt anzeigt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5185ef7461d7e81d/6a16f718839dfa1559dcfcb1/1dd28d3d0509f92d26b0bb5320a2925f7a54c5d9-1440x736.png" alt="Kibana ES|QL - Flughäfen" /><p>Oder Sie könnten eine Ebene hinzufügen, die die Polygone ab dem Index <code>airport_city_boundaries</code> anzeigt, oder noch besser, wie wäre es mit der komplexen <code>ENRICH</code> -Abfrage oben, die Statistiken darüber generiert, wie viele Flughäfen sich in jeder Region befinden?</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt51ee3543bb811d98/6a16f71a8b73cbbe63189df1/679a0a401faa613c7cedddd07c64f614ac2b7144-1440x727.png" alt="Kibana ES|QL – Regionsstatistik" /><h2>Was kommt als Nächstes?</h2><p>Der vorherige Blogbeitrag <a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one">zum Thema Geodaten-Suche</a> konzentrierte sich auf die Verwendung von Funktionen wie <code>ST_INTERSECTS</code> zur Durchführung von Suchvorgängen, die in Elasticsearch seit Version 8.14 verfügbar sind. Und in diesem Blog erfahren Sie, wie Sie die Daten importieren können, die wir für diese Suchvorgänge verwendet haben. Elasticsearch 8.15 brachte jedoch eine besonders interessante Funktion mit sich: <code>ST_DISTANCE</code> , mit der sich effiziente räumliche Distanzsuchen durchführen lassen, und dies wird das Thema des nächsten Blogbeitrags sein!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/geospatial-data-ingest-for-esql</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/geospatial-data-ingest-for-esql</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Craig Taverner]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfc041ebca11476c6/6a16f70560084b31b93c4344/01fde3b1d714f12bf8673140c9f2f940d443de31-1440x823.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 25 Oct 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Geodaten-Suche mit Elasticsearch und ES|QL]]></title>
    <description><![CDATA[Geodaten-Suche in der Elasticsearch Query Language (ES|QL). Elasticsearch verfügt über leistungsstarke Geodaten-Suchfunktionen, die nun in ES|QL integriert werden, um die Benutzerfreundlichkeit und OGC-Vertrautheit deutlich zu verbessern.]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch verfügt seit vielen Jahren über leistungsstarke <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/geospatial-analysis.html">Funktionen für die Geodaten-Suche und -Analyse</a> , aber die API unterschied sich deutlich von dem, was typische GIS-Anwender gewohnt waren. Im vergangenen Jahr haben wir <a href="https://www.elastic.co/search-labs/blog/esql-piped-query-language-goes-ga">die Abfragesprache ES|QL hinzugefügt</a>, eine Pipe-Abfragesprache, die genauso einfach oder sogar noch einfacher als SQL ist. Es eignet sich besonders für die Anwendungsfälle Suche, Sicherheit und Beobachtbarkeit, in denen Elastic hervorragende Leistungen erbringt. Wir fügen außerdem Unterstützung für die Geodaten-Suche und -Analyse innerhalb von ES|QL hinzu, was die Nutzung deutlich vereinfacht, insbesondere für Anwender aus SQL- oder <a href="https://en.wikipedia.org/wiki/Geographic_information_system">GIS-</a> Bereichen.</p><p>Elasticsearch 8.12 und 8.13 führten die grundlegende Unterstützung für Geodaten-Typen in ES|QL ein. Dies wurde durch die Hinzufügung von Geodaten-Suchfunktionen in Version 8.14 deutlich verbessert. Wichtiger noch: Diese Unterstützung wurde so konzipiert, dass sie sich eng an den <a href="https://en.wikipedia.org/wiki/Simple_Features">Simple Feature Access-</a> Standard des <a href="https://en.wikipedia.org/wiki/Open_Geospatial_Consortium">Open Geospatial Consortium (OGC)</a> anlehnt, der auch von anderen räumlichen Datenbanken wie PostGIS verwendet wird. Dadurch wird die Nutzung für GIS-Experten, die mit diesen Standards vertraut sind, deutlich vereinfacht.</p><p>In diesem Blog zeigen wir Ihnen, wie Sie mit ES|QL Geodatenabfragen durchführen und wie sich dies im Vergleich zu den entsprechenden SQL- und Query-DSL-Funktionen verhält. Wir zeigen Ihnen außerdem, wie Sie mit ES|QL räumliche Verknüpfungen durchführen und wie Sie die Ergebnisse in Kibana Maps visualisieren. Bitte beachten Sie, dass sich alle hier beschriebenen Funktionen in der „technischen Vorschau“ befinden. Wir freuen uns über Ihr Feedback, wie wir diese verbessern können.</p><h2>Suche nach Geodaten</h2><p>Beginnen wir mit einer Beispielabfrage:</p>FROM airport_city_boundaries
| WHERE ST_INTERSECTS(
      city_boundary,
      "POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))"::geo_shape
  )
| KEEP abbrev, airport, region, city, city_location
<p>Hierbei wird nach Stadtgrenzenpolygonen gesucht, die sich mit einem rechteckigen Suchpolygon um den internationalen Flughafen Sanya Phoenix (SYX) schneiden.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3897df6bed5d6061/6a17d7c2abe0f29eccdfe861/e48bac8f246c8842f2ea97ddd54910045262aeb1-1440x808.png" alt="ESQL-Geodatensuche" /><p>In einem Beispieldatensatz mit Flughäfen, Städten und Stadtgrenzen findet diese Suche das sich überschneidende Polygon und gibt die gewünschten Felder aus dem übereinstimmenden Dokument zurück:</p><p>Abkürzung</p><p>Flughafen</p><p>Region</p><p>Stadt</p><p>Stadtstandort</p><p>SYX</p><p>Sanya Phoenix Int'l</p><p>天涯区</p><p>Sanya</p><p>Punkt(109.5036 18.2533)</p><p>Das war einfach! Vergleichen Sie dies nun mit der klassischen Elasticsearch Query DSL für dieselbe Abfrage:</p>GET /airport_city_boundaries/_search
{
  "_source": ["abbrev", "airport", "region", "city", "city_location"],
  "query": {
    "geo_shape": {
      "city_boundary": {
        "shape": {
          "type": "polygon",
          "coordinates" : [[
            [109.4, 18.1],
            [109.6, 18.1],
            [109.6, 18.3],
            [109.4, 18.3],
            [109.4, 18.1]
          ]]
        }
      }
    }
  }
}
<p>Beide Abfragen sind in ihrer Absicht einigermaßen klar, aber die ES|QL-Abfrage ähnelt stark SQL. Die gleiche Abfrage in PostGIS sieht folgendermaßen aus:</p>SELECT abbrev, airport, region, city, city_location
FROM airport_city_boundaries
WHERE ST_INTERSECTS(
    city_boundary,
    'SRID=4326;POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))'::geometry
);
<p>Schauen Sie sich das ES|QL-Beispiel noch einmal an. So ähnlich, nicht wahr?</p>FROM airport_city_boundaries
| WHERE ST_INTERSECTS(
      city_boundary,
      "POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))"::geo_shape
  )
| KEEP abbrev, airport, region, city, city_location
<p>Wir haben festgestellt, dass bestehende Benutzer der Elasticsearch API ES|QL als wesentlich einfacher zu bedienen empfinden. Wir gehen davon aus, dass bestehende SQL-Anwender, insbesondere Spatial SQL-Anwender, feststellen werden, dass sich ES|QL sehr vertraut anfühlt und ihnen sehr ähnlich ist.</p><h4>Warum nicht SQL?</h4><p>Und wie sieht es mit Elasticsearch SQL aus? Es existiert schon eine Weile und verfügt über einige Geodatenfunktionen. Elasticsearch SQL wurde jedoch als Wrapper für die ursprüngliche Query-API geschrieben, was bedeutete, dass nur Abfragen unterstützt wurden, die in die ursprüngliche API transpiliert werden konnten. ES|QL hat diese Einschränkung nicht. Da es sich um einen völlig neuen Stack handelt, sind viele Optimierungen möglich, die in SQL nicht möglich waren. Unsere Benchmarks zeigen, dass ES|QL <a href="https://elasticsearch-benchmarks.elastic.co/#tracks/esql/nightly/default/6M">sehr oft schneller ist als die Query API</a>, insbesondere bei Aggregationen!</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt18bda964c8b24e36/6a17d7c3e3179155d22d568a/b8b6c2b2e45850d832805ed1e71e522f4955f53c-1440x813.png" alt="Polygon-Schnittpunkt-Benchmark" /><h2>Unterschiede zu SQL</h2><p>Wie das vorherige Beispiel zeigt, ist ES|QL SQL zwar in gewisser Weise ähnlich, es gibt aber auch einige wichtige Unterschiede. ES|QL ist beispielsweise eine Pipe-Abfragesprache, die mit einem Quellbefehl wie FROM beginnt und dann alle nachfolgenden Befehle mit dem Pipe-Zeichen | miteinander verkettet. Dadurch wird es sehr einfach verständlich, wie jeder Befehl eine Datentabelle empfängt und eine bestimmte Aktion an dieser Tabelle durchführt, z. B. Filtern mit <code>WHERE</code>, Hinzufügen von Spalten mit <code>EVAL</code> oder Durchführen von Aggregationen mit <code>STATS</code>. Anstatt mit <code>SELECT</code> zu beginnen, um die endgültigen Ausgabespalten zu definieren, können ein oder mehrere <code>KEEP</code> -Befehle verwendet werden, wobei der letzte Befehl die endgültigen Ausgaberesultate angibt. Diese Struktur vereinfacht die Argumentation bezüglich der Anfrage.</p><p>Wenn wir uns den Befehl <code>WHERE</code> im obigen Beispiel genauer ansehen, erkennen wir, dass er dem PostGIS-Beispiel sehr ähnlich sieht:</p><p><em>ES|QL</em></p>WHERE ST_INTERSECTS(
    city_boundary,
    "POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))"::geo_shape
)
<p><em>PostGIS</em></p>WHERE ST_INTERSECTS(
    city_boundary,
    'SRID=4326;POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))'::geometry
)
<p>Abgesehen von den Unterschieden bei den Anführungszeichen für Zeichenketten besteht der größte Unterschied darin, wie wir die Zeichenkette in einen räumlichen Datentyp umwandeln. In PostGIS verwenden wir das Suffix <code>::geometry</code> , während wir in ES|QL das Suffix <code>::geo_shape</code> verwenden. Dies liegt daran, dass ES|QL innerhalb von Elasticsearch ausgeführt wird und der Typumwandlungsoperator <code>::</code> verwendet werden kann, um eine Zeichenkette in einen der <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-limitations.html#_supported_types">unterstützten ES|QL-Typen</a> umzuwandeln, in diesem Fall in einen <code>geo_shape</code>. Darüber hinaus implizieren die Typen <code>geo_shape</code> und <code>geo_point</code> in Elasticsearch das räumliche Koordinatensystem WGS84, das häufiger unter der SRID-Nummer 4326 bezeichnet wird. In PostGIS muss dies explizit angegeben werden, daher die Verwendung des Präfixes <code>SRID=4326;</code> für die WKT-Zeichenkette. Wird dieses Präfix entfernt, wird die SRID auf 0 gesetzt, was eher den Elasticsearch-Typen <code>cartesian_point</code> und <code>cartesian_shape</code> entspricht, die nicht an ein bestimmtes Koordinatensystem gebunden sind.</p><p>Sowohl ES|QL als auch PostGIS bieten eine Syntax für Typkonvertierungsfunktionen:</p><p><em>ES|QL</em></p>WHERE ST_INTERSECTS(
    city_boundary,
    TO_GEOSHAPE("POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))")
)
<p><em>PostGIS</em></p>WHERE ST_INTERSECTS(
    city_boundary,
    ST_SetSRID(
      ST_GeomFromText('POLYGON((109.4 18.1, 109.6 18.1, 109.6 18.3, 109.4 18.3, 109.4 18.1))'),
      4326
    )
)
<h2>OGC-Funktionen</h2><p>Elasticsearch 8.14 führt die folgenden vier OGC-Funktionen für die räumliche Suche ein:</p><p>ES|QL</p><p>PostGIS</p><p>Beschreibung</p><p>ST_INTERSECTS</p><p>ST_Schnittpunkte</p><p>Gibt true zurück, wenn sich zwei Geometrien schneiden, und andernfalls false.</p><p>ST_DISJOINT</p><p>ST_Disjoint</p><p>Gibt true zurück, wenn sich zwei Geometrien nicht schneiden, und andernfalls false. Die Umkehrfunktion von ST_INTERSECTS.</p><p>ST_CONTAINS</p><p>ST_Contains</p><p>Gibt true zurück, wenn eine Geometrie eine andere enthält, andernfalls false.</p><p>ST_WITHIN</p><p>ST_Within</p><p>Gibt true zurück, wenn sich eine Geometrie innerhalb einer anderen befindet, und andernfalls false. Das Inverse von ST_CONTAINS.</p><p>Diese Funktionen verhalten sich ähnlich wie ihre PostGIS-Pendants und werden auf die gleiche Weise verwendet. Beispielsweise gibt <code>ST_INTERSECTS</code> true zurück, wenn sich zwei Geometrien schneiden, und andernfalls false. Wenn Sie den Dokumentationslinks in der obigen Tabelle folgen, werden Sie feststellen, dass sich alle ES|QL-Beispiele innerhalb einer <code>WHERE</code> -Klausel nach einer <code>FROM</code> -Klausel befinden, während alle PostGIS-Beispiele literale Geometrien verwenden. Tatsächlich unterstützen beide Plattformen die Verwendung der Funktionen in jedem Teil der Abfrage, in dem sie sinnvoll sind.</p><p>Das erste Beispiel in der PostGIS-Dokumentation für <code>ST_INTERSECTS</code> lautet:</p>SELECT ST_Intersects(
    'POINT(0 0)'::geometry,
    'LINESTRING ( 2 0, 0 2 )'::geometry
);
<p>Das ES|QL-Äquivalent dazu wäre:</p>ROW ST_INTERSECTS(
    "POINT(0 0)"::geo_point,
    "LINESTRING ( 2 0, 0 2 )"::geo_shape
)
<p>Beachten Sie, dass wir im PostGIS-Beispiel die SRID nicht angegeben haben. Dies liegt daran, dass in PostGIS bei Verwendung des Typs <code>geometry</code> alle Berechnungen auf einem planaren Koordinatensystem durchgeführt werden. Wenn also beide Geometrien die gleiche SRID haben, spielt es keine Rolle, welche SRID es ist. In Elasticsearch gilt dies auch für die meisten Funktionen. Es gibt jedoch Ausnahmen, bei denen <code>geo_shape</code> und <code>geo_point</code> sphärische Berechnungen verwenden, wie wir im nächsten Blogbeitrag über die Suche nach räumlichen Distanzen sehen werden.</p><h2>ES|QL Vielseitigkeit</h2><p>Wir haben oben also Beispiele für die Verwendung von räumlichen Funktionen in <code>WHERE</code> -Klauseln und in <code>ROW</code> -Befehlen gesehen. Wo sonst würden sie Sinn machen? Eine sehr nützliche Stelle dafür ist der Befehl <code>EVAL</code> . Mit diesem Befehl können Sie einen Ausdruck auswerten und das Ergebnis zurückgeben. Nehmen wir beispielsweise an, wir wollen feststellen, ob die Schwerpunkte aller Flughäfen, gruppiert nach ihren Ländernamen, innerhalb einer Grenze liegen, die das jeweilige Land umschließt:</p>FROM airports
| EVAL in_uk = ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))"))
| EVAL in_iceland = ST_INTERSECTS(location, TO_GEOSHAPE("POLYGON ((-25.4883 65.5312, -23.4668 66.7746, -18.4131 67.4749, -13.0957 66.2669, -12.3926 64.4159, -20.1270 62.7346, -24.7852 63.3718, -25.4883 65.5312))"))
| EVAL within_uk = ST_WITHIN(location, TO_GEOSHAPE("POLYGON((1.2305 60.8449, -1.582 61.6899, -10.7227 58.4017, -7.1191 55.3291, -7.9102 54.2139, -5.4492 54.0078, -5.2734 52.3756, -7.8223 49.6676, -5.0977 49.2678, 0.9668 50.5134, 2.5488 52.1065, 2.6367 54.0078, -0.9668 56.4625, 1.2305 60.8449))"))
| EVAL within_iceland = ST_WITHIN(location, TO_GEOSHAPE("POLYGON ((-25.4883 65.5312, -23.4668 66.7746, -18.4131 67.4749, -13.0957 66.2669, -12.3926 64.4159, -20.1270 62.7346, -24.7852 63.3718, -25.4883 65.5312))"))
| STATS centroid = ST_CENTROID_AGG(location), count=COUNT() BY in_uk, in_iceland, within_uk, within_iceland
| SORT count ASC
<p>Die Ergebnisse sind erwartungsgemäß: Die Schwerpunkte der britischen Flughäfen liegen innerhalb der Grenzen Großbritanniens und nicht innerhalb der Grenzen Islands, und umgekehrt.</p><p>Schwerpunkt</p><p>Anzahl</p><p>in_uk</p><p>in Island</p><p>innerhalb Großbritanniens</p><p>innerhalb Islands</p><p>PUNKT (-21,946634463965893 64.13187285885215)</p><p>1</p><p>FALSCH</p><p>wahr</p><p>FALSCH</p><p>wahr</p><p>PUNKT (-2,597342072712148 54,33551226578214)</p><p>17</p><p>wahr</p><p>FALSCH</p><p>wahr</p><p>FALSCH</p><p>PUNKT (0,04453958108176276 23,74658354606057)</p><p>873</p><p>FALSCH</p><p>FALSCH</p><p>FALSCH</p><p>FALSCH</p><p>Tatsächlich können diese Funktionen in jedem Teil der Abfrage verwendet werden, in dem ihre Signatur sinnvoll ist. Sie alle nehmen zwei Argumente entgegen, die entweder ein Literal eines räumlichen Objekts oder ein Feld eines räumlichen Typs sind, und sie alle geben einen booleschen Wert zurück. Eine wichtige Überlegung ist, dass das Koordinatenreferenzsystem (CRS) der Geometrien übereinstimmen muss, andernfalls wird ein Fehler zurückgegeben. Das bedeutet, dass Sie die Typen <code>geo_shape</code> und <code>cartesian_shape</code> nicht im selben Funktionsaufruf mischen können. Allerdings können Sie die Typen <code>geo_point</code> und <code>geo_shape</code> mischen, da der Typ <code>geo_point</code> ein Sonderfall des Typs <code>geo_shape</code> ist und beide das gleiche Koordinatenreferenzsystem verwenden. Die Dokumentation zu jeder der oben definierten Funktionen listet die unterstützten Typkombinationen auf.</p><p>Darüber hinaus kann jedes Argument ein räumliches Literal oder ein Feld sein, in beliebiger Reihenfolge. Sie können sogar zwei Felder, zwei Literale, ein Feld und ein Literal oder ein Literal und ein Feld angeben. Die einzige Voraussetzung ist, dass die Datentypen kompatibel sind. Diese Abfrage vergleicht beispielsweise zwei Felder im selben Index:</p>FROM airport_city_boundaries
| EVAL in_city = ST_INTERSECTS(city_location, city_boundary)
| STATS count=COUNT(*) BY in_city
| SORT count ASC
| EVAL cardinality = CASE(count &lt; 10, "very few", count &lt; 100, "few", "many")
| KEEP cardinality, count, in_city
<p>Die Anfrage zielt im Grunde darauf ab, ob sich der Ort innerhalb der Stadtgrenzen befindet, was im Allgemeinen zutreffen sollte, aber es gibt immer Ausnahmen:</p><p>Kardinalität</p><p>Anzahl</p><p>in_city</p><p>wenige</p><p>29</p><p>FALSCH</p><p>viele</p><p>740</p><p>wahr</p><p>Eine weitaus interessantere Frage wäre, ob sich der Flughafenstandort innerhalb der Grenzen der Stadt befindet, die der Flughafen bedient. Der Standort des Flughafens befindet sich jedoch in einem anderen Index als derjenige, der die Stadtgrenzen enthält. Dies erfordert eine Methode, um Daten aus diesen beiden separaten Indizes effektiv abzufragen und zu korrelieren.</p><h2>Räumliche Verknüpfungen</h2><p>ES|QL unterstützt keine <code>JOIN</code> -Befehle, aber Sie können einen Sonderfall eines Joins mit dem <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-commands.html#esql-enrich"><code>ENRICH</code></a><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-commands.html#esql-enrich"> -Befehl</a> erreichen, der sich ähnlich wie ein 'left join' in SQL verhält. Dieser Befehl funktioniert ähnlich wie ein „Left Join“ in SQL und ermöglicht es Ihnen, Ergebnisse aus einem Index mit Daten aus einem anderen Index anzureichern, basierend auf einer räumlichen Beziehung zwischen den beiden Datensätzen.</p><p>Nehmen wir beispielsweise an, wir reichern die Ergebnisse einer Tabelle mit Flughäfen um zusätzliche Informationen über die jeweilige Stadt an, indem wir die Stadtgrenze ermitteln, die den Flughafenstandort enthält, und führen dann einige statistische Auswertungen der Ergebnisse durch:</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary
| MV_EXPAND city_boundary
| EVAL boundary_wkt_length = LENGTH(TO_STRING(city_boundary))
| STATS centroid = ST_CENTROID_AGG(location), count = COUNT(city_location), min_wkt = MIN(boundary_wkt_length), max_wkt = MAX(boundary_wkt_length) BY region
| SORT count DESC
| LIMIT 5
<p>Dies liefert die Top 5 Regionen mit den meisten Flughäfen, zusammen mit dem Schwerpunkt aller Flughäfen, die übereinstimmenden Regionen zugeordnet sind, und der Längenspanne der WKT-Darstellung der Stadtgrenzen innerhalb dieser Regionen:</p><p>Schwerpunkt</p><p>Anzahl</p><p>min_wkt</p><p>max_wkt</p><p>Region</p><p>PUNKT (-32.56093470960719 32.598117914802714)</p><p>90</p><p>207</p><p>207</p><p>null</p><p>PUNKT (-73.94515332765877 40.70366442203522)</p><p>9</p><p>438</p><p>438</p><p>Stadt New York</p><p>PUNKT (-83.10398317873478 42.300230911932886)</p><p>9</p><p>473</p><p>473</p><p>Detroit</p><p>PUNKT (-156.3020245861262 20.176383580081165)</p><p>5</p><p>307</p><p>803</p><p>Hawaii</p><p>PUNKT (-73.88902732171118 45.57078813901171)</p><p>4</p><p>837</p><p>837</p><p>Montréal</p><p>Was ist hier also wirklich geschehen? Wo trat das vermeintliche <code>JOIN</code> auf? Der Kern der Anfrage liegt im Befehl <code>ENRICH</code> :</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary
<p>Dieser Befehl weist Elasticsearch an, die aus dem Index <code>airports</code> abgerufenen Ergebnisse anzureichern und einen Join <code>intersects</code> zwischen dem Feld <code>city_location</code> des ursprünglichen Index und dem Feld <code>city_boundary</code> des Index <code>airport_city_boundaries</code> durchzuführen, den wir bereits in einigen Beispielen verwendet haben. Einige dieser Informationen sind in dieser Abfrage jedoch nicht klar ersichtlich. Was wir sehen, ist der Name einer Anreicherungsrichtlinie <code>city_boundaries</code>, und die fehlenden Informationen sind in dieser Richtliniendefinition enthalten.</p>{
  "geo_match": {
    "indices": "airport_city_boundaries",
    "match_field": "city_boundary",
    "enrich_fields": ["city", "airport", "region", "city_boundary"]
  }
}
<p>Hier sehen wir, dass eine <code>geo_match</code> -Abfrage durchgeführt wird (<code>intersects</code> ist der Standardwert), das Feld, mit dem abgeglichen werden soll, ist <code>city_boundary</code>, und die <code>enrich_fields</code> sind die Felder, die wir dem Originaldokument hinzufügen möchten. Eines dieser Felder, nämlich <code>region</code> wurde tatsächlich als Gruppierungsschlüssel für den Befehl <code>STATS</code> verwendet, was ohne diese 'left join'-Funktion nicht möglich gewesen wäre. Weitere Informationen zu Anreicherungsrichtlinien finden Sie in der <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-setup.html">Anreicherungsdokumentation</a>. Beim Lesen dieser Dokumente werden Sie feststellen, dass darin die Verwendung von Anreicherungsindizes zur Anreicherung von Daten während der Indexierung durch die Konfiguration von Aufnahmepipelines beschrieben wird. Dies ist für ES|QL nicht erforderlich, da der Befehl <code>ENRICH</code> zur Abfragezeit funktioniert. Es genügt, den Anreicherungsindex mit den erforderlichen Daten und der Anreicherungsrichtlinie vorzubereiten und dann den Befehl <code>ENRICH</code> in Ihren ES|QL-Abfragen zu verwenden.</p><p>Möglicherweise stellen Sie auch fest, dass die am häufigsten vorkommende Region <code>null</code> war. Was könnte das bedeuten? Zur Erinnerung: Ich habe diesen Befehl mit einem 'Left Join' in SQL verglichen. Das bedeutet, dass, wenn keine übereinstimmende Stadtgrenze für einen Flughafen gefunden wird, der Flughafen trotzdem zurückgegeben wird, jedoch mit <code>null</code> Werten für die Felder ab dem <code>airport_city_boundaries</code> Index. Es stellte sich heraus, dass es 89 Flughäfen gab, bei denen kein passender Eintrag <code>city_boundary</code> gefunden wurde, und einen Flughafen mit einer Übereinstimmung, bei dem das Feld <code>region</code> den <code>null</code> hatte. Dies führte zu einer Zählung von 90 Flughäfen, bei denen keine <code>region</code> in den Ergebnissen vorkam. Ein weiteres interessantes Detail ist die Notwendigkeit des Befehls <code>MV_EXPAND</code> . Dies ist notwendig, da der Befehl <code>ENRICH</code> für jede Eingabezeile mehrere Ergebnisse zurückgeben kann, und <code>MV_EXPAND</code> hilft dabei, diese Ergebnisse in mehrere Zeilen aufzuteilen, eine für jedes Ergebnis. Dies erklärt auch, warum für "Hawaii" unterschiedliche <code>min_wkt</code> und <code>max_wkt</code> Ergebnisse angezeigt werden: Es gab mehrere Regionen mit dem gleichen Namen, aber unterschiedlichen Grenzen.</p><h2>Kibana-Karten</h2><p>Kibana hat die Unterstützung für Spatial ES|QL in der Kartenanwendung hinzugefügt. Das bedeutet, dass Sie nun ES|QL verwenden können, um in Elasticsearch nach Geodaten zu suchen und die Ergebnisse auf einer Karte zu visualisieren.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt91922eb4ef43d290/6a16f7161949f737bfe7a7b5/bd78470bd8a4bc60f0db7006bd804b8fe87e2fea-1440x683.png" alt="Kibana Layers ES|QL" /><p>Im Menü „Ebenen hinzufügen“ gibt es eine neue Ebenenoption mit der Bezeichnung „ES|QL“. Wie alle bisher beschriebenen Geodatenfunktionen befindet sich auch diese in der „technischen Vorschauphase“. Durch Auswahl dieser Option können Sie der Karte eine Ebene hinzufügen, die auf den Ergebnissen einer ES|QL-Abfrage basiert. Man könnte beispielsweise eine Ebene zur Karte hinzufügen, die alle Flughäfen der Welt anzeigt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5185ef7461d7e81d/6a16f718839dfa1559dcfcb1/1dd28d3d0509f92d26b0bb5320a2925f7a54c5d9-1440x736.png" alt="Kibana ES|QL - Flughäfen" /><p>Oder Sie könnten eine Ebene hinzufügen, die die Polygone ab dem Index <code>airport_city_boundaries</code> anzeigt, oder noch besser, wie wäre es mit der komplexen <code>ENRICH</code> -Abfrage oben, die Statistiken darüber generiert, wie viele Flughäfen sich in jeder Region befinden?</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt51ee3543bb811d98/6a16f71a8b73cbbe63189df1/679a0a401faa613c7cedddd07c64f614ac2b7144-1440x727.png" alt="Kibana ES|QL – Regionsstatistik" /><h2>Was kommt als Nächstes?</h2><p>Vielleicht ist Ihnen aufgefallen, dass wir in zwei der obigen Beispiele noch eine weitere räumliche Funktion <code>ST_CENTROID_AGG</code> eingefügt haben. Dies ist eine Aggregationsfunktion, die im Befehl <code>STATS</code> verwendet wird, und die erste von vielen räumlichen Analysefunktionen, die wir ES|QL hinzufügen wollen. Wir werden darüber bloggen, sobald wir mehr zu zeigen haben!</p><p>Zuvor möchten wir Ihnen jedoch ein besonders spannendes Feature vorstellen, an dem wir gearbeitet haben: die Möglichkeit, räumliche Distanzsuchen durchzuführen – eine der am häufigsten genutzten räumlichen Suchfunktionen von Elasticsearch. Können Sie sich vorstellen, wie die Syntax für Distanzsuchen aussehen könnte? Vielleicht ähnlich einer OGC-Funktion? Bleiben Sie dran für den nächsten Blogbeitrag dieser Reihe, um es herauszufinden!</p><p>Spoiler-Alarm: Elasticsearch 8.15 wurde soeben veröffentlicht und beinhaltet die räumliche Distanzsuche mit ES|QL!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one</guid>
    <category><![CDATA[Python]]></category>
    <category><![CDATA[ES|QL]]></category>
    <dc:creator><![CDATA[Craig Taverner]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd05627be20e89dfb/6a17d7c6414c640256944fdb/de886289dcb56494920875303b622b030b9b810f-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 12 Aug 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>