<?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/jp/search-labs/author/craig-taverner</link>
    </image>
    <link>https://www.elastic.co/jp/search-labs/author/craig-taverner</link>
    <atom:link href="https://www.elastic.co/jp/search-labs/rss/author/craig-taverner.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[jp]]></language>
    <lastBuildDate>Tue, 22 Sep 2026 18:41:14 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Kibana を使用して地理空間データを Elasticsearch に取り込み、ES|QL で使用できるようにする]]></title>
    <description><![CDATA[Kibana と csv 取り込みプロセッサを使用して、Elasticsearch に地理空間データを取り込んで、Elasticsearch クエリ言語 (ES|QL) で検索する方法。Elasticsearch には強力な地理空間検索機能があり、これが ES|QL にも導入され、使いやすさと OGC への親しみやすさが大幅に向上しました。ただし、これらの機能を使用するには、地理空間データが必要です。]]></description>
    <content:encoded><![CDATA[<p>最近、Elasticsearch の新しい強力な<a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one"> パイプ</a><a href="https://www.elastic.co/search-labs/blog/esql-piped-query-language-goes-ga"> クエリ言語</a><a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one"> である ES|QL の 新しい</a><a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one"> 地理空間検索 機能</a> の使用方法を説明するブログを公開しました。これらの機能を使用するには、Elasticsearch に地理空間データが必要です。そこでこのブログでは、地理空間データを取り込む方法と、それを ES|QL クエリで使用する方法を紹介します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfc041ebca11476c6/6a16f70560084b31b93c4344/01fde3b1d714f12bf8673140c9f2f940d443de31-1440x823.jpg" alt="ESQL 地理空間検索" /><h2>Kibanaを使用した地理空間データのインポート</h2><p>前回のブログの例に使用したデータは、統合テストのために社内で使用しているデータに基づいています。便宜上、Kibana を使用して簡単にインポートできるいくつかの CSV ファイルの形式でここに含めました。データには空港、都市、都市境界が混在しています。データは以下からダウンロードできます:</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">空港.csv</a></p><ul><li><p>これには 3 つのデータセットの結合が含まれます。</p><ul><li><p><a href="https://www.naturalearthdata.com/downloads/10m-cultural-vectors/airports/">Natural Earth</a>の空港（名称、場所、関連データ）</p></li><li><p><a href="https://simplemaps.com/data/world-cities">SimpleMaps</a>からの都市の位置</p></li><li><p><a href="https://www.partow.net/miscellaneous/airportdatabase/">世界の空港データベース</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">空港都市境界.csv</a></p><ul><li><p>これには、上記の空港名と都市名が 1 つの新しいソースと結合されたものが含まれています。</p><ul><li><p><a href="https://www.openstreetmap.org/">OpenStreetMap</a>の都市境界</p></li></ul></li></ul></li></ul><p>ご想像のとおり、私たちは ES|QL の地理空間機能をテストできるようにすることを目的として、これらのデータ ソースを上記の 2 つのファイルに結合するのに時間を費やしました。これは、特定のデータ ニーズとまったく同じではないかもしれませんが、これによって、何が可能かについてのアイデアが得られると思います。特に、いくつかの興味深い点について説明したいと思います。</p><ul><li><p>地理空間フィールドを含むデータを他のインデックス可能なデータと一緒にインポートする</p></li><li><p><code>geo_point</code>と<code>geo_shape</code>両方のデータをインポートし、クエリで一緒に使用します</p></li><li><p>空間関係を使用して結合できる 2 つのインデックスにデータをインポートする</p></li><li><p>将来のインポートを容易にするための取り込みパイプラインの作成（Kibana 以外）</p></li><li><p><code>csv</code> 、 <code>convert</code> 、 <code>split</code></p></li></ul><p>このブログでは CSV データの操作について説明しますが、<a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html"> Kibana</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"> </a><a href="https://www.elastic.co/guide/en/kibana/current/import-geospatial-data.html">方法はいくつかある こと</a> を理解することが重要です。マップ アプリケーション内では、CSV、GeoJSON、ESRI ShapeFiles などの区切りデータをアップロードでき、マップ内に直接図形を描画することもできます。このブログでは、Kibana ホームページから CSV ファイルをインポートすることに焦点を当てます。</p><h3>空港の輸入</h3><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> 、対処する必要がある興味深い癖がいくつかあります。まず、列を区切る追加の空白がありますが、これは CSV ファイルでは一般的ではありません。次に、 <code>type</code>フィールドは複数値フィールドであるため、個別のフィールドに分割する必要があります。最後に、一部のフィールドは文字列ではないため、適切な型に変換する必要があります。これらはすべて、Kibana の CSV インポート機能を使用して実行できます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt393bc416bf425301/6a16f707839dfa1e86dcfca9/b1afd8c95973bec32f229a9adfaef14680b09a8e-1944x478.png" alt="Kibana アップロード - プレビュー" /><p>Kibana のホームページから始めましょう。「統合を追加して開始する」というセクションがあり、そこに「ファイルをアップロードする」というリンクがあります。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte12fc741edab20d3/6a16f709acf088600fbe98bf/996372bb3a52859cc840bd1d8f984a33a0e7ada3-1180x410.png" alt="Kibanaホーム - ファイルをアップロード" /><p>このリンクをクリックすると、「ファイルのアップロード」ページに移動します。ここで<code>airports.csv</code>ファイルをドラッグ アンド ドロップすると、Kibana がファイルを分析し、データのプレビューを表示します。区切り文字がコンマであること、最初の行がヘッダー行であることが自動的に検出されるはずです。ただし、すべてのフィールドが<code>text</code>または<code>keyword</code>であると想定すると、列間の余分な空白が削除されず、フィールドの種類も判別されなかった可能性があります。これを修正する必要があります。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf65a09ec0c7a61ad/6a16f70ad7c0227aedde626f/1d9ffa6cdbc0d67a228be1a747ec1ebda6a63099-1800x538.png" alt="Kibana アップロード - プレビュー" /><p><code>Override settings</code>をクリックし、 <code>Should trim fields</code>のチェックボックスをオンにして、 <code>Apply</code>クリックして設定を閉じます。ここで、フィールドのタイプを修正する必要があります。これは次のページでご覧いただけますので、 <code>Import</code>をクリックしてください。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltda9a5f85d8e693dc/6a16f70c60084b72f53c4348/a97aceffb1858eae26a213336913505ae9923b03-1800x526.png" alt="Kibanaアップロード - インポート" /><p>まずインデックス名を選択し、次に<code>Advanced</code>を選択してフィールド マッピングと取り込みプロセッサ ページに移動します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt56705083cdd9eb18/6a16f70d66c4f93350f8bdbb/058b0fb09da0b8d7f9c9b0a9c83b8b485ce43925-1440x629.png" alt="Kibana アップロード - フィールドマッピング" /><p>ここでは、インデックスのフィールド マッピングと、データをインポートするための取り込みパイプラインの両方に変更を加える必要があります。まず、Kibana は<code>scalerank</code>フィールドを<code>long</code>として自動検出したと思われますが、 <code>location</code>フィールドと<code>city_location</code>フィールドを<code>keyword</code>として誤って認識しました。これらを<code>geo_point</code>に編集すると、マッピングは次のようになります。</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>ここではある程度の柔軟性がありますが、選択したタイプによって、フィールドのインデックス作成方法や、可能なクエリの種類が影響を受けることに注意してください。たとえば、 <code>location</code> <code>keyword</code>のままにしておくと、地理空間検索クエリを実行することはできません。同様に、 <code>elevation</code> <code>text</code>のままにしておくと、数値範囲のクエリを実行することはできません。</p><p>ここで、取り込みパイプラインを修正します。Kibana が上記の<code>scalerank</code> <code>long</code>として自動検出した場合、フィールドを<code>long</code>に変換するプロセッサも追加されます。<code>elevation</code>フィールドに同様のプロセッサを追加して、今回は<code>double</code>に変換する必要があります。この変換が確実に実行されるようにパイプラインを編集します。これを保存する前に、 <code>type</code>フィールドを複数のフィールドに分割する変換をもう 1 つ実行する必要があります。次の構成で、パイプラインに<code>split</code>プロセッサを追加します。</p>{
  "split": {
    "field": "type",
    "separator": ":",
    "ignore_missing": true
  }
}<p>最終的な取り込みパイプラインは次のようになります。</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><code>location</code>フィールドと<code>city_location</code>フィールドには変換プロセッサを追加していないことに注意してください。これは、フィールド マッピングの<code>geo_point</code>タイプが、これらのフィールドのデータのWKT形式をすでに理解しているためです。<code>geo_point</code>型は、 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-point.html">WKT、GeoJSON など、</a>さまざまな形式を理解できます。たとえば、CSV ファイルに<code>latitude</code>と<code>longitude</code>の 2 つの列がある場合、これらを 1 つの<code>geo_point</code>フィールドに結合するには、 <code>script</code>または<code>set</code>プロセッサを追加する必要がありました (例:<code>"set": {"field": "location", "value": "{{lat}},{{lon}}"}</code> ）。</p><p>これでファイルをインポートする準備が整いました。<code>Import</code>をクリックすると、定義したマッピングと取り込みパイプラインを使用してデータがインデックスにインポートされます。データの取り込み中にエラーが発生した場合は、Kibana によってここで報告されるので、ソース データまたは取り込みパイプラインを編集して再試行できます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte81621425c7289c5/6a16f70f839dfaf608dcfcad/55dde2940c7aba66ce8257d15007ef797b8a5107-1440x415.png" alt="Kibanaアップロード - インポート" /><p>新しい取り込みパイプラインが作成されたことに注意してください。これは、Kibana の<code>Stack Management</code>セクションに移動し、 <code>Ingest pipelines</code>を選択すると表示されます。ここで、作成したパイプラインを確認し、必要に応じて編集できます。実際、 <code>Ingest pipelines</code>セクションは取り込みパイプラインの作成とテストに使用できます。これは、さらに複雑な取り込みを行う予定がある場合に非常に便利な機能です。</p><p>このデータをすぐに調べたい場合は後のセクションに進んでください。ただし、都市の境界もインポートしたい場合は読み続けてください。</p><h3>都市境界のインポート</h3><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>で利用可能な都市境界ファイルは、前の例よりもインポートが少し簡単です。これには、都市の境界を<code>POLYGON</code>として WKT で表現した<code>city_boundary</code>フィールドと、都市の位置を<code>geo_point</code>表現した<code>city_location</code>フィールドが含まれています。このデータは空港データと同様の方法でインポートできますが、いくつか違いがあります。</p><ul><li><p>自動検出されなかったため、オーバーライド設定<code>Has header row</code>を選択する必要がありました</p></li><li><p>データにはすでに余分な空白が除去されていたため、フィールドをトリミングする必要はありませんでした。</p></li><li><p>すべての型が文字列または空間型であったため、取り込みパイプラインを編集する必要はありませんでした。</p></li><li><p>ただし、フィールドマッピングを編集して、 <code>city_boundary</code>フィールドを<code>geo_shape</code>に設定し、 <code>city_location</code>フィールドを <code>geo_point</code></p></li></ul><p>最終的なフィールド マッピングは次のようになります。</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>以前の<code>airports.csv</code>インポートと同様に、 <code>Import</code>をクリックするだけでデータがインデックスにインポートされます。データは、編集したマッピングと Kibana が定義した取り込みパイプラインを使用してインポートされます。</p><h3>開発ツールで地理空間データを探索する</h3><p>Kibana では、インデックス化されたデータを「Discover」で探索するのが一般的です。ただし、ES|QL クエリを使用して独自のアプリを作成することが目的である場合は、生の Elasticsearch API にアクセスしてみる方が興味深いかもしれません。Kibana には、クエリの記述を試すための便利なコンソールがあります。これは<code>Dev Tools</code>コンソールと呼ばれ、Kibana サイドバーにあります。このコンソールは Elasticsearch クラスターと直接通信し、クエリの実行、インデックスの作成などに使用できます。</p><p>次のことを試してください。</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>これにより、次の結果が得られます。</p><p>距離</p><p>略語</p><p>名前</p><p>場所</p><p>国</p><p>市</p><p>標高</p><p>273418.05776847183</p><p>ハム</p><p>ハンブルク</p><p>ポイント (10.005647830925 53.6320011640866)</p><p>ドイツ</p><p>ノルダーシュテット</p><p>17.0</p><p>337534.653466062</p><p>テキサス</p><p>ベルリン・テーゲル国際空港</p><p>ポイント (13.2903090925074 52.5544287044101)</p><p>ドイツ</p><p>ホーエン・ノイエンドルフ</p><p>38.0</p><p>483713.15032266214</p><p>OSL</p><p>オスロ・ガーデモエン</p><p>ポイント (11.0991032762581 60.1935783171386)</p><p>ノルウェー</p><p>オスロ</p><p>208.0</p><p>522538.03148094116</p><p>BMA</p><p>ブロンマ</p><p>ポイント (17.9456175406145 59.3555902065112)</p><p>スウェーデン</p><p>ストックホルム</p><p>15.0</p><p>522538.03148094116</p><p>アーン</p><p>アーランダ</p><p>ポイント (17.9307299016916 59.6511203397372)</p><p>スウェーデン</p><p>ストックホルム</p><p>38.0</p><p>624274.8274399083</p><p>ダス</p><p>デュッセルドルフ国際空港</p><p>ポイント (6.76494446612174 51.2781820420774)</p><p>ドイツ</p><p>デュッセルドルフ</p><p>45.0</p><p>633388.6966435644</p><p>PRG</p><p>ルジン</p><p>ポイント (14.2674849854076 50.1076511703671)</p><p>チェコ</p><p>プラハ</p><p>381.0</p><p>635911.1873311149</p><p>アムス</p><p>スキポール</p><p>ポイント (4.76437693232812 52.3089323889822)</p><p>オランダ</p><p>ホーフトドルプ</p><p>-3.0</p><p>670864.137958866</p><p>フランス</p><p>フランクフルト国際空港</p><p>ポイント (8.57182286907608 50.0506770895207)</p><p>ドイツ</p><p>フランクフルト</p><p>111.0</p><p>683239.2529970079</p><p>ワウ</p><p>オケシー国際空港</p><p>ポイント (20.9727263383587 52.171026749259)</p><p>ポーランド</p><p>ピアセチュノ</p><p>111.0</p><h2>Kibana Maps で地理空間データを視覚化する</h2><p>Kibana Maps は、地理空間データを視覚化するための強力なツールです。これを使用すると、各レイヤーが異なるデータセットを表す複数のレイヤーを持つマップを作成できます。データはさまざまな方法でフィルタリング、集計、スタイル設定できます。このセクションでは、前のセクションでインポートしたデータを使用して、Kibana Maps でマップを作成する方法を説明します。</p><p>Kibana メニューで、 <code>Analytics</code> -&gt; <code>Maps</code>に移動して新しいマップ ビューを開きます。<code>Add Layer</code>をクリックして<code>Documents</code>を選択し、データ ビュー<code>airports</code>を選択して、レイヤー スタイルを編集し、 <code>elevation</code>フィールドを使用してマーカーに色を付けます。これにより、各空港の高さが簡単にわかります。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdcc4736d88c1abc9/6a16f7102b835f7353f4afca/9e63726d7c059331e6e20e474f8abee53dc2cbb4-840x388.png" alt="Kibanaマップ - 空港レイヤースタイル" /><p>マップを保存するには、「変更を保持」をクリックします。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ec3cc535b5c21d8/6a16f71375879ec091fe15dc/32ad1dadb5d341a2b66662c58638b781122fc22c-2852x1528.png" alt="Kibanaマップ - 空港" /><p>次に、 <code>airport_city_boundaries</code>データ ビューを選択して、2 番目のレイヤーを追加します。今回は、 <code>city_boundary</code>フィールドを使用してレイヤーのスタイルを設定し、塗りつぶしの色を薄い青に設定します。これにより、地図上に都市の境界が表示されます。空港マーカーが最上部になるようにレイヤーの順序を変更してください。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2932d7ff4a7206c9/6a16f7156f7f0409f09145c7/53dd65026f9a98c13f2cc4f9328a79242f0b70de-2854x1510.png" alt="Kibanaマップ - 都市境界レイヤースタイル" /><h2>空間結合</h2><p>ES|QL は<code>JOIN</code>コマンドをサポートしていませんが、 <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">コマンド</a>を使用して特殊な結合を実現できます。このコマンドは SQL の「左結合」に似た動作をし、2 つのデータセット間の空間関係に基づいて、1 つのインデックスの結果を別のインデックスのデータで強化することができます。</p><p>たとえば、空港の場所を含む都市の境界を見つけることで、空港のテーブルからの結果に、空港がサービスを提供する都市に関する追加情報を付加し、結果に対していくつかの統計を実行してみましょう。</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>最初にエンリッチインデックスを準備せずにこのクエリを実行すると、次のようなエラー メッセージが表示されます。</p>cannot find enrich policy [city_boundaries]<p>これは、前述したように、ES|QL が真の<code>JOIN</code>コマンドをサポートしていないためです。その重要な理由の 1 つは、Elasticsearch が分散システムであり、結合はスケーリングが難しい高コストの操作であることです。ただし、 <code>ENRICH</code>コマンドは、クラスター全体に複製された特別に準備されたエンリッチ インデックスを利用し、各ノードでローカル結合を実行できるため、非常に効率的です。</p><p>これをよりよく理解するために、上記のクエリの<code>ENRICH</code>コマンドに注目してみましょう。</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary<p>このコマンドは、Elasticsearch に、 <code>airports</code>インデックスから取得された結果を強化し、元のインデックスの<code>city_location</code>フィールドと、前のいくつかの例で使用した<code>airport_city_boundaries</code>インデックスの<code>city_boundary</code>フィールドの間で<code>intersects</code>結合を実行するように指示します。しかし、この情報の一部はこのクエリでは明確に表示されません。表示されるのはエンリッチポリシーの名前<code>city_boundaries</code>であり、不足している情報はそのポリシー定義内にカプセル化されています。</p>{
  "geo_match": {
    "indices": "airport_city_boundaries",
    "match_field": "city_boundary",
    "enrich_fields": ["city", "airport", "region", "city_boundary"]
  }
}<p>ここでは、 <code>geo_match</code>クエリ ( <code>intersects</code>がデフォルト) が実行され、照合するフィールドが<code>city_boundary</code>であり、 <code>enrich_fields</code>が元のドキュメントに追加するフィールドであることがわかります。これらのフィールドの 1 つである<code>region</code>は、実際には<code>STATS</code>コマンドのグループ化キーとして使用されていましたが、これはこの「左結合」機能がなければ実行できませんでした。エンリッチ ポリシーの詳細については、<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-setup.html">エンリッチのドキュメント</a>を参照してください。</p><p>Elasticsearch のエンリッチ インデックスとポリシーは、もともと、別の準備されたエンリッチ インデックスのデータを使用して、インデックス作成時にデータをエンリッチするために設計されました。ただし、ES|QL では、 <code>ENRICH</code>コマンドはクエリ時に機能し、取り込みパイプラインを使用する必要はありません。これは実質的に SQL <code>LEFT JOIN</code>と非常に似ていますが、2 つのインデックスを結合することはできず、左側の通常のインデックスと、右側の特別に準備されたエンリッチ インデックスのみを結合できます。</p><p>どちらの場合でも、取り込みパイプライン用でも ES|QL で使用する場合でも、エンリッチ インデックスとポリシーを設定するためにいくつかの準備手順を実行する必要があります。上記ですでに<code>airport_city_boundaries</code>インデックスをインポートしましたが、これを<code>ENRICH</code>コマンドのエンリッチ インデックスとして直接使用することはできません。まず、次の 2 つの手順を実行する必要があります。</p><ul><li><p>上記のエンリッチ ポリシーを作成して、ソース インデックス、照合するソース インデックス内のフィールド、一致した場合に返されるフィールドを定義します。</p></li><li><p>このポリシーを実行して、エンリッチ インデックスを作成します。これにより、元のソース インデックスをより効率的なデータ構造に読み取り、クラスター全体にコピーすることで、特別な内部インデックスが構築されます。</p></li></ul><p>エンリッチ ポリシーは、次のコマンドを使用して作成できます。</p>PUT /_enrich/policy/city_boundaries
{
  "match": {
    "indices": "airport_city_boundaries",
    "match_field": "city_boundary",
    "enrich_fields": ["city", "airport", "region", "city_boundary"]
  }
}<p>そして、次のコマンドを使用してポリシーを実行できます。</p>POST /_enrich/policy/city_boundaries/_execute<p><code>airport_city_boundaries</code>インデックスの内容を変更した場合は、エンリッチ インデックスに反映された変更を確認するためにこのポリシーを再実行する必要があることに注意してください。ここで、元の ES|QL クエリをもう一度実行してみましょう。</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>これは、空港が最も多い上位 5 つの地域と、一致する地域を持つすべての空港の重心、およびそれらの地域内の都市境界の WKT 表現の長さの範囲を返します。</p><p>重心</p><p>カウント</p><p>地域</p><p>ポイント (-12.13908685930073331.024386116624648)</p><p>126</p><p>ヌル</p><p>ポイント (-83.1039831787347842.300230911932886)</p><p>3</p><p>デトロイト</p><p>ポイント (39.74537850357592 47.21613017376512)</p><p>3</p><p>городской округ Батайск</p><p>ポイント (-156.8098678719252320.476673701778054)</p><p>3</p><p>ハワイ</p><p>ポイント (-73.9451533276587740.70366442203522）</p><p>3</p><p>ニューヨーク市</p><p>ポイント (-83.1039831787347842.300230911932886)</p><p>3</p><p>デトロイト</p><p>ポイント (-76.6687301918864324.306286952923983)</p><p>2</p><p>ニュープロビデンス</p><p>ポイント (-3.0252167768776417 51.39245774131268)</p><p>2</p><p>カーディフ</p><p>ポイント (-115.4099348466843432.73126147687435）</p><p>2</p><p>メヒカリ市</p><p>ポイント (41.790108773857355 50.302146775648)</p><p>2</p><p>Центральный район</p><p>ポイント (-73.8890273217111845.57078813901171)</p><p>2</p><p>モントリオール</p><p>また、最も頻繁に見つかった地域は<code>null</code>であったことにも気付くでしょう。これは何を意味するのでしょうか?このコマンドを SQL の「左結合」に例えたことを思い出してください。つまり、空港に一致する都市境界が見つからない場合でも、その空港は返されますが、 <code>airport_city_boundaries</code>インデックスのフィールドには<code>null</code>値が含まれます。一致する<code>city_boundary</code>が見つからなかった空港が 125 か所あり、 <code>region</code>フィールドが<code>null</code>である一致する空港が 1 か所あることがわかりました。これにより、結果に<code>region</code>が含まれない空港が 126 件見つかりました。ユースケースですべての空港を都市の境界に一致させる必要がある場合は、ギャップを埋めるために追加のデータを入手する必要があります。次の 2 つの点を決定する必要があります。</p><ul><li><p><code>airport_city_boundaries</code>インデックス内のどのレコードに<code>city_boundary</code>フィールドがありませんか</p></li><li><p><code>airports</code>インデックス内のどのレコードが<code>ENRICH</code>コマンドを使用しても一致しないか (つまり、交差しない）</p></li></ul><h2>Kibana Maps の地理空間データに ES|QL を使用する</h2><p>Kibana は、マップ アプリケーションに Spatial ES|QL のサポートを追加しました。つまり、ES|QL を使用して Elasticsearch で地理空間データを検索し、その結果をマップ上に視覚化できるようになりました。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt91922eb4ef43d290/6a16f7161949f737bfe7a7b5/bd78470bd8a4bc60f0db7006bd804b8fe87e2fea-1440x683.png" alt="Kibana レイヤー ES|QL" /><p>レイヤー追加メニューに、「ES|QL」という新しいレイヤー オプションがあります。これまで説明したすべての地理空間機能と同様に、これは「技術プレビュー」段階です。このオプションを選択すると、ES|QL クエリの結果に基づいてマップにレイヤーを追加できます。たとえば、世界中のすべての空港を表示するレイヤーをマップに追加できます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5185ef7461d7e81d/6a16f718839dfa1559dcfcb1/1dd28d3d0509f92d26b0bb5320a2925f7a54c5d9-1440x736.png" alt="キバナ ES|QL - 空港" /><p>または、 <code>airport_city_boundaries</code>インデックスからポリゴンを表示するレイヤーを追加することもできます。さらに良い方法として、各地域に空港がいくつあるかという統計を生成する、上記の複雑な<code>ENRICH</code>クエリはどうでしょうか。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt51ee3543bb811d98/6a16f71a8b73cbbe63189df1/679a0a401faa613c7cedddd07c64f614ac2b7144-1440x727.png" alt="Kibana ES|QL - 地域統計" /><h2>新しいエクスペリエンス</h2><p>前回の<a href="https://www.elastic.co/search-labs/blog/esql-geospatial-search-part-one">地理空間検索</a>ブログでは、Elasticsearch 8.14 以降で利用可能な<code>ST_INTERSECTS</code>などの関数を使用して検索を実行することに焦点を当てました。このブログでは、これらの検索に使用したデータをインポートする方法を説明します。ただし、Elasticsearch 8.15 には特に興味深い関数<code>ST_DISTANCE</code>が搭載されており、これを使用して効率的な空間距離検索を実行できます。これが次のブログのトピックになります。</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[ES|QL を使用した Elasticsearch 地理空間検索]]></title>
    <description><![CDATA[Elasticsearch クエリ言語 (ES|QL) での地理空間検索。Elasticsearch には強力な地理空間検索機能があり、これが ES|QL にも導入され、使いやすさと OGC への親しみやすさが大幅に向上しました。]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch は長年にわたって強力な<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/geospatial-analysis.html">地理空間検索および分析機能を</a>提供してきましたが、その API は一般的な GIS ユーザーが使い慣れたものとはまったく異なっていました。過去 1 年間で、SQL と同じくらい、あるいは SQL よりも簡単なパイプ クエリ言語<a href="https://www.elastic.co/search-labs/blog/esql-piped-query-language-goes-ga">である ES|QL クエリ言語を追加しました</a>。これは、Elastic が得意とする検索、セキュリティ、可観測性のユースケースに特に適しています。また、ES|QL 内での地理空間検索と分析のサポートも追加されており、特に SQL または<a href="https://en.wikipedia.org/wiki/Geographic_information_system">GIS</a>コミュニティ出身のユーザーにとって、はるかに使いやすくなります。</p><p>Elasticsearch 8.12 および 8.13 では、ES|QL に地理空間タイプの基本サポートが導入されました。これは、8.14 で地理空間検索機能が追加されたことにより大幅に強化されました。<a href="https://en.wikipedia.org/wiki/Open_Geospatial_Consortium">さらに重要なことは、このサポートは、PostGIS などの他の空間データベースで使用されている Open</a> Geospatial Consortium (OGC) の<a href="https://en.wikipedia.org/wiki/Simple_Features"> Simple Feature Access</a> 標準に厳密に準拠するように設計されているため、これらの標準に精通している GIS 専門家にとって非常に使いやすくなっていることです。</p><p>このブログでは、ES|QL を使用して地理空間検索を実行する方法と、それを SQL およびクエリ DSL と同等の機能と比較する方法を紹介します。また、ES|QL を使用して空間結合を実行する方法と、結果を Kibana Maps で視覚化する方法も紹介します。ここで説明する機能はすべて「テクニカル プレビュー」段階であるため、改善方法について皆様からのフィードバックをお待ちしています。</p><h2>地理空間データの検索</h2><p>クエリの例から始めましょう:</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>これは、三亜鳳凰国際空港 (SYX) の周囲の長方形の検索ポリゴンと交差する都市境界ポリゴンの検索を実行します。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3897df6bed5d6061/6a17d7c2abe0f29eccdfe861/e48bac8f246c8842f2ea97ddd54910045262aeb1-1440x808.png" alt="ESQL 地理空間検索" /><p>空港、都市、都市境界のサンプル データセットでは、この検索により交差するポリゴンが検索され、一致するドキュメントから必要なフィールドが返されます。</p><p>略語</p><p>空港</p><p>地域</p><p>市</p><p>都市の場所</p><p>シックス</p><p>三亜フェニックス国際空港</p><p>天外区</p><p>三亜</p><p>点(109.5036 18.2533)</p><p>簡単でした！次に、同じクエリの従来の Elasticsearch クエリ DSL と比較してみましょう。</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>どちらのクエリも意図はかなり明確ですが、ES|QL クエリは SQL によく似ています。PostGIS での同じクエリは次のようになります。</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>ES|QL の例を振り返ってみましょう。とても似ていますよね？</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>Elasticsearch API の既存のユーザーにとって、ES|QL の方がはるかに使いやすいことがわかりました。既存の SQL ユーザー、特に Spatial SQL ユーザーにとって、ES|QL は使い慣れたものと非常によく似ていると感じられるものと期待しています。</p><h4>なぜSQLではないのですか?</h4><p>Elasticsearch SQL についてはどうですか?しばらく前から存在しており、いくつかの地理空間機能を備えています。ただし、Elasticsearch SQL は元のクエリ API の上にラッパーとして記述されたため、元の API にトランスパイルできるクエリのみがサポートされていました。ES|QL にはこの制限はありません。完全に新しいスタックであるため、SQL では不可能だった多くの最適化が可能になります。私たちのベンチマークでは、ES|QL は、特に集計において、<a href="https://elasticsearch-benchmarks.elastic.co/#tracks/esql/nightly/default/6M">クエリ API よりも非常に高速である</a>ことが示されています。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt18bda964c8b24e36/6a17d7c3e3179155d22d568a/b8b6c2b2e45850d832805ed1e71e522f4955f53c-1440x813.png" alt="多角形交差ベンチマーク" /><h2>SQLとの違い</h2><p>前の例から、ES|QL は SQL と多少似ていることは明らかですが、いくつか重要な違いもあります。たとえば、ES|QL はパイプ クエリ言語であり、FROM などのソース コマンドで開始し、後続のすべてのコマンドをパイプ | 文字で連結します。これにより、各コマンドがデータ テーブルを受け取って、そのテーブルに対して何らかのアクション ( <code>WHERE</code>によるフィルタリング、 <code>EVAL</code>による列の追加、 <code>STATS</code>による集計の実行など) を実行する方法が非常に簡単に理解できるようになります。最終的な出力列を定義するために<code>SELECT</code>から始めるのではなく、1 つ以上の<code>KEEP</code>コマンドがあり、最後のコマンドで最終的な出力結果を指定できます。この構造により、クエリに関する推論が簡素化されます。</p><p>上記の例の<code>WHERE</code>コマンドに注目すると、PostGIS の例と非常によく似ていることがわかります。</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>ポストGIS</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>文字列引用文字の違いは別として、最も大きな違いは、文字列を空間型に型キャストする方法にあります。PostGIS では<code>::geometry</code>サフィックスを使用し、ES|QL では<code>::geo_shape</code>サフィックスを使用します。これは、ES|QL が Elasticsearch 内で実行され、型キャスト演算子<code>::</code>を使用して文字列を<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-limitations.html#_supported_types">サポートされているいずれかの ES|QL 型</a>(この場合は<code>geo_shape</code> ) に変換できるためです。さらに、Elasticsearch の<code>geo_shape</code>および<code>geo_point</code>タイプは、WGS84 と呼ばれる空間座標系を意味し、通常は SRID 番号 4326 を使用して参照されます。PostGIS ではこれを明示的にする必要があるため、WKT 文字列に<code>SRID=4326;</code>プレフィックスを使用します。そのプレフィックスが削除されると、SRID は 0 に設定され、特定の座標系に関連付けられていない Elasticsearch タイプ<code>cartesian_point</code>および<code>cartesian_shape</code>に似たものになります。</p><p>ES|QL と PostGIS はどちらも型変換関数の構文も提供しています。</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>ポストGIS</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関数</h2><p>Elasticsearch 8.14 では、次の 4 つの OGC 空間検索関数が導入されています。</p><p>ES|QL</p><p>ポストGIS</p><p>説明</p><p>ST_INTERSECTS</p><p>ST_交差</p><p>2 つのジオメトリが交差する場合は true を返し、そうでない場合は false を返します。</p><p>ST_DISJOINT</p><p>ST_分離</p><p>2 つのジオメトリが交差しない場合は true を返し、そうでない場合は false を返します。ST_INTERSECTS の逆。</p><p>ST_CONTAINS</p><p>ST_Contains</p><p>1 つのジオメトリに別のジオメトリが含まれている場合は true を返し、含まれていない場合は false を返します。</p><p>ST_WITHIN</p><p>ST_以内</p><p>1 つのジオメトリが別のジオメトリ内にある場合は true を返し、そうでない場合は false を返します。ST_CONTAINS の逆。</p><p>これらの関数は PostGIS の対応する関数と同様に動作し、同じように使用されます。たとえば、 <code>ST_INTERSECTS</code> 2 つのジオメトリが交差する場合は true を返し、そうでない場合は false を返します。上記の表のドキュメント リンクに従うと、すべての ES|QL の例が<code>FROM</code>句の後の<code>WHERE</code>句内にあるのに対し、すべての PostGIS の例はリテラル ジオメトリを使用していることに気付くでしょう。実際、どちらのプラットフォームでも、意味のあるクエリのどの部分でも関数の使用がサポートされています。</p><p><code>ST_INTERSECTS</code>の PostGIS ドキュメントの最初の例は次のとおりです。</p>SELECT ST_Intersects(
    'POINT(0 0)'::geometry,
    'LINESTRING ( 2 0, 0 2 )'::geometry
);
<p>ES|QL でこれに相当するものは次のとおりです。</p>ROW ST_INTERSECTS(
    "POINT(0 0)"::geo_point,
    "LINESTRING ( 2 0, 0 2 )"::geo_shape
)
<p>PostGIS の例では SRID を指定していないことに注意してください。これは、PostGIS で<code>geometry</code>タイプを使用する場合、すべての計算が平面座標系で実行されるため、両方のジオメトリが同じ SRID を持つ場合、SRID が何であるかは問題にならないためです。Elasticsearch でも、これはほとんどの関数に当てはまりますが、 <code>geo_shape</code>と<code>geo_point</code>球面計算が使用されるという例外があります。これについては、空間距離検索に関する次のブログで説明します。</p><h2>ES|QLの汎用性</h2><p>上記では、 <code>WHERE</code>句と<code>ROW</code>コマンドで空間関数を使用する例を見てきました。他にどこで意味を成すのでしょうか?非常に便利な場所の 1 つは、 <code>EVAL</code>コマンドです。このコマンドを使用すると、式を評価して結果を返すことができます。たとえば、国名ごとにグループ化されたすべての空港の重心が、国の境界内にあるかどうかを判断します。</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>結果は予想通りで、英国の空港の重心は英国の境界内にあり、アイスランドの境界内にはなく、その逆も同様です。</p><p>重心</p><p>カウント</p><p>英国</p><p>アイスランド</p><p>英国内</p><p>アイスランド内</p><p>ポイント (-21.94663446396589364.13187285885215)</p><p>1</p><p>間違い</p><p>true</p><p>間違い</p><p>true</p><p>ポイント (-2.597342072712148 54.33551226578214)</p><p>17</p><p>true</p><p>間違い</p><p>true</p><p>間違い</p><p>ポイント (0.04453958108176276 23.74658354606057)</p><p>873</p><p>間違い</p><p>間違い</p><p>間違い</p><p>間違い</p><p>実際、これらの関数は、そのシグネチャが意味を成すクエリのどの部分でも使用できます。これらはすべて、リテラル空間オブジェクトまたは空間型のフィールドのいずれかである 2 つの引数を取り、ブール値を返します。重要な考慮事項の 1 つは、ジオメトリの座標参照システム (CRS) が一致している必要があることです。一致していない場合はエラーが返されます。つまり、同じ関数呼び出しで<code>geo_shape</code>型と<code>cartesian_shape</code>型を混在させることはできません。ただし、 <code>geo_point</code>タイプは<code>geo_shape</code>タイプの特殊なケースであり、両方とも同じ座標参照系を共有しているため、 <code>geo_point</code>タイプと<code>geo_shape</code>タイプを混在させることができます。上記で定義された各関数のドキュメントには、サポートされている型の組み合わせがリストされています。</p><p>さらに、どちらの引数も、空間リテラルまたはフィールドを任意の順序で指定できます。2 つのフィールド、2 つのリテラル、フィールドとリテラル、またはリテラルとフィールドを指定することもできます。唯一の要件は、タイプに互換性があることです。たとえば、次のクエリは同じインデックス内の 2 つのフィールドを比較します。</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>このクエリは基本的に、都市の場所が都市の境界内にあるかどうかを尋ねます。これは通常当てはまるはずですが、常に例外があります。</p><p>基数</p><p>カウント</p><p>市内</p><p>少し</p><p>29</p><p>間違い</p><p>多くの</p><p>740</p><p>true</p><p>さらに興味深い質問は、空港の場所が、その空港がサービスを提供する都市の境界内にあるかどうかです。ただし、空港の位置は、都市の境界を含むインデックスとは異なるインデックスに存在します。これには、これら 2 つの個別のインデックスからデータを効果的にクエリして相関させる方法が必要です。</p><h2>空間結合</h2><p>ES|QL は<code>JOIN</code>コマンドをサポートしていませんが、SQL の「左結合」と同様に動作する<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">コマンド</a>を使用して、特殊な結合を実現できます。このコマンドは SQL の「左結合」に似た動作をし、2 つのデータセット間の空間関係に基づいて、1 つのインデックスの結果を別のインデックスのデータで強化することができます。</p><p>たとえば、空港の場所を含む都市の境界を見つけることで、空港のテーブルからの結果に、空港がサービスを提供する都市に関する追加情報を付加し、結果に対していくつかの統計を実行してみましょう。</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>これは、空港が最も多い上位 5 つの地域と、一致する地域を持つすべての空港の重心、およびそれらの地域内の都市境界の WKT 表現の長さの範囲を返します。</p><p>重心</p><p>カウント</p><p>最小wkt</p><p>最大wkt</p><p>地域</p><p>ポイント (-32.5609347096071932.598117914802714)</p><p>90</p><p>207</p><p>207</p><p>ヌル</p><p>ポイント (-73.9451533276587740.70366442203522）</p><p>9</p><p>438</p><p>438</p><p>ニューヨーク市</p><p>ポイント (-83.1039831787347842.300230911932886)</p><p>9</p><p>473</p><p>473</p><p>デトロイト</p><p>ポイント (-156.302024586126220.176383580081165)</p><p>5</p><p>307</p><p>803</p><p>ハワイ</p><p>ポイント (-73.8890273217111845.57078813901171)</p><p>4</p><p>837</p><p>837</p><p>モントリオール</p><p>それで、ここで実際に何が起こったのでしょうか?<code>JOIN</code>はどこで発生したのでしょうか?クエリの核心は<code>ENRICH</code>コマンドにあります。</p>FROM airports
| ENRICH city_boundaries ON city_location WITH airport, region, city_boundary
<p>このコマンドは、Elasticsearch に、 <code>airports</code>インデックスから取得された結果を強化し、元のインデックスの<code>city_location</code>フィールドと、前のいくつかの例で使用した<code>airport_city_boundaries</code>インデックスの<code>city_boundary</code>フィールドの間で<code>intersects</code>結合を実行するように指示します。しかし、この情報の一部はこのクエリでは明確に表示されません。表示されるのはエンリッチポリシーの名前<code>city_boundaries</code>であり、不足している情報はそのポリシー定義内にカプセル化されています。</p>{
  "geo_match": {
    "indices": "airport_city_boundaries",
    "match_field": "city_boundary",
    "enrich_fields": ["city", "airport", "region", "city_boundary"]
  }
}
<p>ここでは、 <code>geo_match</code>クエリ ( <code>intersects</code>がデフォルト) が実行され、照合するフィールドが<code>city_boundary</code>であり、 <code>enrich_fields</code>が元のドキュメントに追加するフィールドであることがわかります。これらのフィールドの 1 つである<code>region</code>は、実際には<code>STATS</code>コマンドのグループ化キーとして使用されていましたが、これはこの「左結合」機能がなければ実行できませんでした。エンリッチ ポリシーの詳細については、<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-setup.html">エンリッチのドキュメント</a>を参照してください。これらのドキュメントを読んでいくと、取り込みパイプラインを構成することによって、インデックス作成時にデータを拡充するための拡充インデックスの使用について説明されていることに気付くでしょう。ES|QL では、 <code>ENRICH</code>コマンドがクエリ時に機能するため、これは必要ありません。必要なデータとエンリッチポリシーを使用してエンリッチインデックスを準備し、ES|QL クエリで<code>ENRICH</code>コマンドを使用するだけで十分です。</p><p>また、最も頻繁に見つかった地域は<code>null</code>であったことにも気付くでしょう。これは何を意味するのでしょうか?このコマンドを SQL の「左結合」に例えたことを思い出してください。つまり、空港に一致する都市境界が見つからない場合でも、その空港は返されますが、 <code>airport_city_boundaries</code>インデックスのフィールドには<code>null</code>値が含まれます。一致する<code>city_boundary</code>が見つからなかった空港が 89 か所あり、 <code>region</code>フィールドが<code>null</code>である一致する空港が 1 か所あることがわかりました。これにより、結果に<code>region</code>が含まれない空港が 90 件見つかりました。もう 1 つの興味深い点は、 <code>MV_EXPAND</code>コマンドの必要性です。これが必要なのは、 <code>ENRICH</code>コマンドが入力行ごとに複数の結果を返す場合があり、 <code>MV_EXPAND</code>これらの結果を結果ごとに 1 つずつ複数の行に分割するのに役立つためです。これにより、「ハワイ」が異なる<code>min_wkt</code>と<code>max_wkt</code>結果を表示する理由も明らかになります。同じ名前でありながら境界が異なる複数の地域が存在したためです。</p><h2>Kibanaマップ</h2><p>Kibana は、マップ アプリケーションに Spatial ES|QL のサポートを追加しました。つまり、ES|QL を使用して Elasticsearch で地理空間データを検索し、その結果をマップ上に視覚化できるようになりました。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt91922eb4ef43d290/6a16f7161949f737bfe7a7b5/bd78470bd8a4bc60f0db7006bd804b8fe87e2fea-1440x683.png" alt="Kibana レイヤー ES|QL" /><p>レイヤー追加メニューに、「ES|QL」という新しいレイヤー オプションがあります。これまで説明したすべての地理空間機能と同様に、これは「技術プレビュー」段階です。このオプションを選択すると、ES|QL クエリの結果に基づいてマップにレイヤーを追加できます。たとえば、世界中のすべての空港を表示するレイヤーをマップに追加できます。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5185ef7461d7e81d/6a16f718839dfa1559dcfcb1/1dd28d3d0509f92d26b0bb5320a2925f7a54c5d9-1440x736.png" alt="キバナ ES|QL - 空港" /><p>または、 <code>airport_city_boundaries</code>インデックスからポリゴンを表示するレイヤーを追加することもできます。さらに良い方法として、各地域に空港がいくつあるかという統計を生成する、上記の複雑な<code>ENRICH</code>クエリはどうでしょうか。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt51ee3543bb811d98/6a16f71a8b73cbbe63189df1/679a0a401faa613c7cedddd07c64f614ac2b7144-1440x727.png" alt="Kibana ES|QL - 地域統計" /><h2>新しいエクスペリエンス</h2><p>上記の 2 つの例では、さらに別の空間関数<code>ST_CENTROID_AGG</code>が組み込まれていることに気付いたかもしれません。これは、 <code>STATS</code>コマンドで使用される集計関数であり、ES|QL に追加する予定の多くの空間分析機能の最初のものです。もっと詳しく紹介できるようになったら、ブログで紹介します!</p><p>その前に、私たちが取り組んできた特に興味深い機能、つまり Elasticsearch で最もよく使用される空間検索機能の 1 つである空間距離検索を実行する機能について詳しく説明したいと思います。距離検索の構文がどのようになるか想像できますか?おそらく OGC 関数に似ていますか?詳細については、このシリーズの次のブログをお読みください。</p><p>ネタバレ注意: Elasticsearch 8.15 がリリースされました。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>