GeoJSONデータ関数の使用

GeoJson仕様は、地形(ジオメトリ)を表すJSONオブジェクトの構造およびコンテンツを定義します。GeoJson仕様によれば、JSONオブジェクトはジオメトリ・オブジェクトになるためにはtypeおよびcoordinatesという2つのフィールドが必要です。ここで、typeフィールドの値にはジオメトリの種類を指定し、座標の値は、要素がジオメトリの形状を定義する配列である必要があります。

すべての種類のジオメトリが、一連の位置で指定されます。ただし、行文字列やポリゴンの場合、実際の幾何学的図形は、位置を結ぶ線によって形成されます。GeoJson仕様では、水平軸と垂直軸がそれぞれ経度と緯度である、(フラットな)デカルト座標系の点を結ぶ直線として、2点間の線を定義します。

JSONオブジェクトをジオメトリとして解釈し、特定の条件を満たすジオメトリを含む行を検索できる様々な組込み関数があります。

例に従って、拡張DDL入力モードを使用してOCIコンソールから表を作成します。DDL文を次に示します。

CREATE TABLE IF NOT EXISTS PointsOfInterest (
    id INTEGER, poi JSON,
PRIMARY KEY(id));

DDL文を使用して表を作成するステップは、「シングルトン表の作成: 拡張DDL入力モード」を参照してください。

OCIコンソールから作成された表にデータをロードするには、表名をクリックします。表の詳細が表示されます。「データをアップロード」をクリックします。「アップロードするファイルの選択」をクリックし、アップロードするJSONファイルを指定します。GeoJSONデータのDDLおよびJSONファイルは、こちらからダウンロードできます

ジオインサイド

GeoJSON境界ジオメトリ内のジオメトリを特定します。

boolean geo_inside(any*, any*)

この関数は、最初のパラメータが指すジオメトリが、2番目のパラメータが指すポリゴン内に完全に含まれているかどうかを判断します。

2つのパラメータのいずれかが単一の有効なジオメトリ・オブジェクトを返さない場合は、そのことがコンパイル時に検出されると、エラーが発生します

実行時の動作は次のとおりです。

ノート:ポリゴンの内側とは、ポリゴンの境界を定義する線形リング上のポイントを除く、ポリゴン領域内のすべてのポイントのことです。

例:北カリフォルニアの自然公園を検索します。

SELECT t.poi.name AS park_name,
t.poi.address.street AS park_location
FROM PointsOfInterest t
WHERE t.poi.kind = "nature park"
AND geo_inside(t.poi.location,
              { "type" : "polygon",
                "coordinates": [[
                  [-
120.1135253906249, 36.99816565700228],
                  [-119.0972900390625, 37.391981943533544],
                  [-119.2840576171875, 37.97451499202459],
                  [-120.2069091796874, 38.035112420612975],
                  [-122.3822021484375, 37.74031329210266],
                  [-122.2283935546875, 37.15156050223665],
                  [-121.5362548828124, 36.85325222344018],
                  [-120.1135253906249, 36.99816565700228]
                ]]
             });

説明:

結果:

{"park_name":"portola redwoods state park",
"park_location":"15000 Skyline Blvd"}

地理交差

GeoJSONジオメトリと交差するジオメトリを特定します。

boolean geo_intersect(any*, any*)

1番目と2番目のパラメータany*には、任意のジオメトリ・オブジェクトを指定できます。

この関数は、パラメータとして指定された2つのジオメトリに共通するポイントがあるかどうかを判断します。2つのパラメータのいずれかが単一の有効なジオメトリ・オブジェクトを返さない場合は、そのことがコンパイル時に検出されると、エラーが発生します

実行時の動作は次のとおりです。

両方のパラメータがそれぞれ単一のジオメトリ・オブジェクトを返す場合、2つのジオメトリに共通するポイントがあればtrueを返し、そうでない場合はfalseを返します。

例: テキサスでは、地下水供給へのアクセスの規制を検討しています。帯水層は、水を含む透水層、岩盤の割れ目または未固結の物質からなる地下層です。政府は、帯水層に非常に近い場所に新たな規制を課す必要があります。

帯水層の座標はすでにマップされています。影響を受ける各郡の郡政府に新しい規制の協議に参加するよう通知できるように、その帯水層と交差するテキサス州のすべての郡を識別する必要があります。

SELECT t.poi.county AS County_needs_regulation,
t.poi.contact AS Contact_phone
FROM PointsOfInterest t WHERE
geo_intersect(
    t.poi.location,
    {

     "type" : "polygon",
      "coordinates": [
          [
            [-97.668457031249, 29.34387539941801],
            [-95.207519531258, 29.19053283229458],
            [-92.900390625653, 30.37287518811801],
            [-94.636230468752, 32.21280106801518],
            [-97.778320312522, 32.45415593941475],
            [-99.799804687541, 31.18460913574325],
            [-97.668457031249, 29.34387539941801]
          ]
        ]
    }
);

説明:

結果:

{"County_needs_regulation":"Tarrant","Contact_phone":"469 745 5687"}
{"County_needs_regulation":"Kinga","Contact_phone":"469 384 7612"}

地理距離

2つの地理空間オブジェクト間の距離を決定します。

double geo_distance(any*, any*)

1番目と2番目のパラメータany*には、任意のジオメトリ・オブジェクトを指定できます。

この関数は2つの入力ジオメトリ間の測地距離を返します。返される距離は、1つ目のポイントが1つ目のジオメトリに属し、2つ目のポイントが2つ目のジオメトリに属しているポイントのペアの距離の最小値として定義されます。このような2つのポイントの間の距離は、ポイントを結ぶ測地線の長さであります。

測地線の概要

2点間の測量線は地球の楕円体表面上の2点間に描画できる最短の線である。簡易な、ただしより実例的な定義のため、地球の表面が球体であると想定します。次に、地球上の2点間の測地線は、これらの点に対応する大円の2点の間にある劣な弧です。つまり、地球の中心によって定義された球面と2点で定義された円の交差で形成される円になります。

次の図は、ロサンゼルスとロンドンの間の測地線と直線の違いを示しています。

geodetic-vs-straight-line.jpgの説明が続きます

図geodetic-vs-straight-line.jpgの説明

2つのパラメータのいずれかが単一の有効なジオメトリ・オブジェクトを返さない場合は、コンパイル時に検出された場合は、エラーが発生します

実行時の動作は次のとおりです。

それ以外の場合、関数は2つの入力ジオメトリ間の測地距離をメートル単位で返します。

ノート:結果は距離を基準に昇順にソートされます(最短距離が最初に表示されます)。

例: 指定の場所から最も近いレストランまでの距離はどれくらいですか。

SELECT
t.poi.name AS restaurant_name,
t.poi.address.street AS street_name,
geo_distance(
    t.poi.location,
    {
       "type" : "point",
       "coordinates": [-
121.94034576416016,37.2812239247177]
    }
) AS distance_in_meters
FROM PointsOfInterest t
WHERE t.poi.kind = "restaurant" ;

説明:

結果:

{"restaurant_name":"Coach Sports Bar & Grill","street_name":"80 Edward St","distance_in_meters":799.2645323337218}
{"restaurant_name":"Ricos Taco","street_name":"80 East Boulevard St","distance_in_meters":976.5361117138553}
{"restaurant_name":"Effie's Restaurant and Bar","street_name":"80 Woodeard St","distance_in_meters":2891.0508307646282}

現在の場所から最も近いレストランまでの距離は799 mです。

地域内距離

ポイントに近接する地理空間オブジェクトを決定します。

boolean geo_within_distance(any*, any*,double)

1番目と2番目のパラメータany*には、任意のジオメトリ・オブジェクトを指定できます。

この関数は、1番目のジオメトリが2番目のジオメトリからN mの距離内にあるかどうかを判断します。

2つのパラメータのいずれかが単一の有効なジオメトリ・オブジェクトを返さない場合は、コンパイル時に検出された場合は、エラーが発生します

実行時の動作は次のとおりです。

最終的に、両方のパラメータがそれぞれ単一のジオメトリ・オブジェクトを返す場合、1番目のジオメトリが2番目のジオメトリからN m以内の距離にあればtrueを返します。Nは3番目のパラメータで返される数値です。それ以外の場合はfalseを返します。2つのジオメトリの間の距離は、1つ目のポイントが1つ目のジオメトリに属し、2つ目のポイントが2つ目のジオメトリに属しているポイントのペアの距離の最小値として定義されます。Nが負の数の場合は、0に設定されます。

例: 市役所はこの先5 km以内にありますか。距離はどれだけですか。

SELECT t.poi.address.street AS city_hall_address,
geo_distance(
    t.poi.location,
    {
        "type" : "point",
        "coordinates" : [-120.653828125,38.85682013474361]
    }

) AS distance_in_meters
FROM PointsOfInterest t
WHERE t.poi.kind = "city hall" AND
geo_within_distance(
    t.poi.location,
    {
        "type" : "point",
        "coordinates" : [-120.653828125,38.85682013474361]
    },
    5000
);

説明:

結果:

{"city_hall_address":"70 North 1st street","distance_in_meters":1736.0144040331768}

市役所は現在の場所から1736 m(1.73 km)です。

近い

ポイントに近接する地理空間オブジェクトを決定します。

boolean geo_near(any*, any*, double)

1番目と2番目のパラメータany*には、任意のジオメトリ・オブジェクトを指定できます。

この関数は、1番目のジオメトリが2番目のジオメトリからN mの距離内にあるかどうかを判断します。

2つのパラメータのいずれかが単一の有効なジオメトリ・オブジェクトを返さない場合は、そのことがコンパイル時に検出されると、エラーが発生します

実行時の動作は次のとおりです。

最終的に、最初の2つのパラメータの両方がそれぞれ単一のジオメトリ・オブジェクトを返す場合、1番目のジオメトリが2番目のジオメトリからN m以内の距離にあればtrueを返します。Nは3番目のパラメータで返される数値です。それ以外の場合はfalseを返します。

ノート: geo_nearは、内部でgeo_within_distanceに変換され、2つのジオメトリ間の距離に(暗黙的な) ORDER BYを指定します。ただし、問合せに(明示的な) ORDER BYがすでに存在する場合、距離による順序付けは実行されません。geo_near関数はWHERE句にのみ使用できます。この場合、最上位レベルの述語(ORまたはNOT演算子の下にネストされていない)にする必要があります。

例1: 指定した場所の3km以内に病院はありますか。

SELECT
t.poi.name AS hospital_name,
t.poi.address.street AS hospital_address
FROM PointsOfInterest t
WHERE t.poi.kind = "hospital"
AND
geo_near(
    t.poi.location,
    {"type" : "point",
     "coordinates" : [-122.03493933105469,37.32949164059004]
    },
    3000
);

説明:

結果:

{"hospital_name":"St. Marthas hospital","hospital_address":"18000 West Blvd"}
{"hospital_name":"Memorial hospital","hospital_address":"10500 South St"}

例2:指定の場所から現在の1マイル以内にあるガソリング・スタンドまでどれくらいの距離がありますか。

SELECT
t.poi.address.street AS gas_station_address,
geo_distance(
    t.poi.location,
    {
        "type" : "point",
        "coordinates" : [-121.90768646240233,37.292081740702365]
    }
) AS distance_in_meters
FROM PointsOfInterest t
WHERE t.poi.kind = "gas station" AND
geo_near(
    t.poi.location,
    {
        "type" : "point",
        "coordinates" : [-121.90768646240233,37.292081740702365]
    },
    1600
);

説明:

結果:

{"gas_station_address":"33 North Avenue","distance_in_meters":886.7004173859665}

次の1マイル以内にある最も近いガソリン・スタンドまでの実際の距離は886mです。

ジオメトリ

地理空間オブジェクトを検証します。

boolean geo_is_geometry(any*)

パラメータany*には、任意のジオメトリ・オブジェクトを指定できます。

この関数は、指定された入力が有効なジオメトリ・オブジェクトであるかどうかを判断します。

例: 市役所を指す場所が有効なジオメトリ・オブジェクトであるかどうかを判断します。

SELECT geo_is_geometry(t.poi.location) AS city_hall
FROM PointsOfInterest t
WHERE t.poi.kind = "city hall"

説明: 関数geo_is_geometryを使用して、指定された場所が有効なジオメトリ・オブジェクトかどうかを判断します。

結果:

{ "city_hall" : true}

関連トピック