在這篇文章中我們將會介紹如何在 MongoDB 中處理地理空間資料,透過 GeoJSON 的資料格式來執行地理空間資料的操作。
我們在使用 Google Map 查詢位置資訊時,可以在 URL 中的 "@" 後發現有一組座標資訊的數值,如下圖中我們使用 Google Map 查詢「台北101」的網址中,在 @ 後的數值組 "25.033976,121.5623502" 依序分別為 緯度 latitude 及 經度 longitude。
而 MongoDB 支持 GeoJSON 這個專門用來儲存地理位置資訊的資料格式。
GeoJSON 是一種專門處理地理資訊(GIS)結構的 JSON 標準格式。 一個 GeoJSON 物件可以用來代表點(Point)、線(LineString)、多邊形(Polygon)等幾何結構,以及特徵(Feature)的集合,或是一系列的特徵(FeatureCollection)。
GeoJSON 物件必須使用嵌入式文件(embedded document)的形式,而 field 欄位有 type 及 coordinate:
關於 GeoJSON,詳細可以參考官方文件。
接著來實作 point 類別的 GeoJSON,我們新增一個「台北 101」位置資訊的 GeoJSON:db.taiwan.insertOne({name: "Taipei 101", position: {type: "Point", coordinates: [121.5623502, 25.033976]}})
使用 find()
來查看剛建立的 GeoJSON object:db.taiwan.find().pretty()
可以看到在 position 中的兩個 field 分別儲存了 type 類別及 coordinates 座標的資訊。
先使用 findOne()
來檢視 restaurant.json 這個有 25359 個 documents 的 collection 的資料結構:db.restaurant.findOne()
接著使用第一筆餐廳的經緯度到 Google Map 查詢:(40.579505, -73.98241999999999)
假設目前的位置是第一個餐廳的位置:(40.5795091, -73.984614)
我們先建位置的索引:db.restaurant.createIndex({location: "2dsphere"})
來查看剛建的索引:db.restaurant.getIndexes()
此時,可以透過以下指令來查詢方圓 300 公尺內的餐廳:db.restaurant.find({ location: { $nearSphere: { $geometry: { type: "Point", coordinates: [-73.984614, 40.5795091] }, $maxDistance: 300 } } })
來講解一下指令中的其中三個部分:
$nearSphere
:查詢距離幾公尺內的點$geometry
:查詢的基準點$maxDistance
:查詢的範圍為幾公尺如果我們將最大範圍改成 100 公尺:maxDistance: 100
如果我們想要針對查詢結果進行排序,距離由小到大做排序,可以使用 聚合 的方式來達成:db.restaurant.aggregate([{ $geoNear: {near: { type: "Point", coordinates: [-73.984614, 40.5795091] }, distanceField: "dist.calculated", maxDistance: 100, includeLocs: "dist.location", spherical: true }}]).pretty()
可以從結果得知,最近的餐廳距離 52 公尺,第二近的餐廳距離 86 公尺。
我們將在這小節介紹如何判斷是否在同一個區域內。
先使用 findOne()
來查看 neighborhood.json 這個地理資料:db.neighborhood.findOne()
可以看出來 neighborhood.json 中的每筆資料都是由多個點組成的多邊形區域範圍。而共有 9 個區域範圍:db.neighborhood.find().count()
假設要判斷的位置是 (40.60855546746685, -73.94187230011019)。
使用以下指令來查詢這個位置是否在 neighborhood 中的任一個區域範圍中:db.neighborhood.findOne({ geometry: { $geoIntersects: { $geometry: { type: "Point", coordinates: [-73.94187230011019, 40.60855546746685]}}}})
從查詢結果可以發現 (40.60855546746685, -73.94187230011019) 這個位置位於 "Madison" 這個區域內。
今天介紹了如何在 MongoDB 中進行對 GeoJSON 資料的操作,下一篇開始會進入 MongoDB 中最重要的觀念 - 聚合 Aggregation。