使用 GeoJSON 資料函數
GeoJson 規格定義應代表地球上地理形狀 (稱為幾何) 之 JSON 物件的結構與內容。根據 GeoJson 規格,若要讓 JSON 物件成為幾何物件,它必須有兩個名為 type 和 coordinates 的欄位,其中類型欄位的值會指定幾何種類,座標的值必須是其元素定義幾何圖形的陣列。
根據一組位置來指定所有種類的幾何。但是,對於線字串和多邊形,實際幾何圖形是由連接其位置的線組成。GeoJson 規格將兩個點之間的線條定義為直線,以連接 (平坦) 笛卡兒座標系統中的點,其水平軸與垂直軸分別為經度與緯度。
有多種內建函數可將 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*)
-
第一個參數
any*可以是任何幾何物件。 -
第二個參數
any*必須是多邊形。
此函數會確定第一個參數所指向的幾何圖形是否完全包含在第二個參數所指向的多邊形中。
如果兩個參數中的任一個都未傳回單一有效幾何物件,且在編譯時可偵測到該物件,函數就會發出錯誤。
執行階段行為如下:
-
如果任何參數傳回 0 或超過 1 個項目,則傳回 false。
-
如果任一參數傳回 NULL,則傳回 NULL。
-
如果任何參數 (執行時期) 傳回的物件不是有效的幾何物件,則傳回 false。
-
如果第二個參數傳回非多邊形的幾何物件,則傳回 false。
-
如果兩個參數都傳回單一幾何物件,而第二個幾何是多邊形。
-
如果第一個幾何圖形完全包含在第二個多邊形內 (即其所有點均屬於多邊形的內部),則傳回 true。
-
否則會傳回 false。
-
備註:多邊形的內部是多邊形區域中的所有點,但定義多邊形邊界的線性環上的點除外。
範例:尋找北加州的自然公園。
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]
]]
});
說明:
-
您可以查詢
PointsOfInterest表格來篩選 nature park 的資料列。 -
您可以指定多邊形作為
geo_inside函數的第二個參數。 -
您指定的多邊形座標會對應至美國加州北部部分的座標。
-
只有當自然公園的位置完全包含在指定的位置點內時,
geo_inside函數才會傳回資料列。
結果:
{"park_name":"portola redwoods state park",
"park_location":"15000 Skyline Blvd"}
地理交集
決定與 GeoJSON 幾何圖形相交的幾何圖形。
boolean geo_intersect(any*, any*)
第一個和第二個參數 any* 可以是任何幾何物件。
此函數會判斷指定為參數的兩個幾何是否有任何共通點。如果兩個參數中的任一個都未傳回單一有效幾何物件,且在編譯時可偵測到該物件,函數就會發出錯誤。
執行階段行為如下:
-
如果任何參數傳回 0 或超過 1 個項目,則傳回 false。
-
如果任一參數傳回 NULL,則傳回 NULL。
-
如果任何參數 (執行時期) 傳回的物件不是有效的幾何物件,則傳回 false。
如果兩個參數都傳回單一幾何物件,則如果兩個幾何有共通點,函數就會傳回 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]
]
]
}
);
說明:
-
上述查詢會擷取與水層位置相交的位置。也就是說,如果位置座標與水層的位置有任何共通點。
-
您可以使用
geo_intersect來查看位置的座標是否有任何與指定之 Aquifer 座標共同的點。
結果:
{"County_needs_regulation":"Tarrant","Contact_phone":"469 745 5687"}
{"County_needs_regulation":"Kinga","Contact_phone":"469 384 7612"}
地理距離
決定兩個空間物件之間的距離。
double geo_distance(any*, any*)
第一個和第二個參數 any* 可以是任何幾何物件。
此函數會傳回兩個輸入幾何之間的大地距離。傳回的距離是第一個點屬於第一個幾何圖形和第二個點至第二個幾何圖形之任一對點之間的最小距離。這兩個點之間,它們的距離是連接點的地球線長度。
大地測量線概觀
介於 2 個點的地球線是最短的線,可以繪製在地球橢球面上的 2 個點之間。對於簡化但更具說明性的定義,假設地球表面為球體的一刻。然後,地球上兩個點之間的大地線是與點相對應之大圓上兩個點之間的小弧,即由球體的交點和由地球的中心和兩個點定義的平面形成的圓。
下圖顯示洛杉磯與倫敦之間的大地線與直線之間的差異。

geodetic-vs-straight-line.jpg 圖解描述
如果兩個參數中的任一個都未傳回單一有效幾何物件,且在編譯時可偵測到該物件,函數就會發出錯誤。
執行階段行為如下:
-
如果任何參數傳回零或超過 1 個項目,則傳回 -1。
-
如果任一參數傳回 NULL,則傳回 NULL。
-
如果任一參數不是幾何物件,則傳回 -1。
否則,此函數會傳回 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" ;
說明:
-
您可以查詢
PointsOfInterest表格來篩選餐廳的資料列。 -
您提供正確的位置點,並使用
geo_distance函數來決定距離。
結果:
{"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 公尺。
距離內地理
決定與點相鄰的地理空間物件。
boolean geo_within_distance(any*, any*,double)
第一個和第二個參數 any* 可以是任何幾何物件。
此函數會決定第一個幾何圖形是否在距離第二個幾何圖形的 N 公尺之內。
如果兩個參數中的任一個都未傳回單一有效幾何物件,且在編譯時可偵測到該物件,函數就會發出錯誤。
執行階段行為如下:
-
如果任何參數傳回 0 或超過 1 個項目,則傳回 false。
-
如果前兩個參數中任一個傳回 NULL,則傳回 NULL。
-
如果前兩個參數中的任一個傳回不是有效幾何物件的項目,則傳回 false。
最後,如果兩個參數傳回單一幾何物件,則如果第一個幾何在 N 公尺與第二個幾何之間的距離內,則傳回 true,其中 N 是第三個參數傳回的數字;否則傳回 false。2 個幾何之間的距離定義為第一個點屬於第一個幾何,第二個點至第二個幾何之任一對點的距離之間的最小值。若 N 為負數,則設為 0。
範例:市政廳接下來 5 公里嗎?有多遠?
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
);
說明:
-
您可以查詢
PointsOfInterest表格來篩選市政廳的資料列。 -
您可以使用
geo_within_distance函數來篩選指定位置 5 公里 (5000 公尺) 內的市政廳。 -
您也可以使用
geo_distance函數擷取您所在位置與市政廳之間的實際距離。
結果:
{"city_hall_address":"70 North 1st street","distance_in_meters":1736.0144040331768}
市中心距離目前地點有 1736 米 (1.73 公里)。
地理位置
決定與點相鄰的地理空間物件。
boolean geo_near(any*, any*, double)
第一個和第二個參數 any* 可以是任何幾何物件。
此函數會決定第一個幾何圖形是否在距離第二個幾何圖形的 N 公尺之內。
如果兩個參數中的任一個都未傳回單一有效幾何物件,且在編譯時可偵測到該物件,函數就會發出錯誤。
執行階段行為如下:
-
如果任何參數傳回 0 或超過 1 個項目,則傳回 false。
-
如果前兩個參數中任一個傳回 NULL,則傳回 NULL。
-
如果前兩個參數中的任一個傳回不是有效幾何物件的項目,則傳回 false。
最後,如果前兩個參數中的兩個參數傳回單一幾何物件,則如果第一個幾何在 N 公尺與第二個幾何之間的距離內 (其中 N 是第三個參數傳回的數字),則會傳回 true;否則傳回 false。
備註:將 geo_near 內部轉換為 geo_within_distance 加上 (隱含) 兩個幾何之間的距離順序。不過,如果查詢已有 (明確) 排序依據,則不會執行依距離排序。geo_near 函數只能出現在 WHERE 子句中,其中必須是一個最上層述詞,例如,不在 OR 或 NOT 運算子底下。
範例 1:指定地點的 3 公里內是否有醫院?
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
);
說明:
-
您可以查詢
PointsOfInterest表格來篩選醫院的資料列。 -
您可以使用
geo_near功能來篩選指定地點 3000 公尺以內的醫院。
結果:
{"hospital_name":"St. Marthas hospital","hospital_address":"18000 West Blvd"}
{"hospital_name":"Memorial hospital","hospital_address":"10500 South St"}
範例 2:距離指定地點的下一個英里內的燃氣站是多遠?
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
);
說明:
-
您可以查詢
PointsOfInterest表格來篩選燃氣站的資料列。 -
您可以使用
geo_near功能,在指定位置的 1 英里 (1600 公尺) 內篩選燃氣站。 -
您也可以使用
geo_distance函數擷取您所在位置與燃氣站之間的實際距離。
結果:
{"gas_station_address":"33 North Avenue","distance_in_meters":886.7004173859665}
下一英里內與最近加油站的實際距離為 886 公尺。
geo_is_ 幾何
驗證地理空間物件。
boolean geo_is_geometry(any*)
參數 any* 可以是任何幾何物件。
此函數會判斷指定的輸入是否為有效的幾何物件。
-
如果參數傳回零或超過 1 個項目,則傳回 false。
-
如果參數傳回 NULL,則傳回 NULL。
-
如果輸入是單一有效的幾何物件,則傳回 true。否則為 false。
範例:決定指向市政廳的位置是否為有效的幾何物件。
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}