MongoDB系列五(地理空間索引與查詢).

来源:https://www.cnblogs.com/jmcui/archive/2018/04/13/8782887.html
-Advertisement-
Play Games

一、經緯度表示方式 MongoDB 中對經緯度的存儲有著自己的一套規範(主要是為了可以在該欄位上建立地理空間索引)。包括兩種方式,分別是 Legacy Coordinate Pairs (這個詞實在不知道怎麼翻譯...) 和 GeoJSON 。 Legacy Coordinate Pairs Leg ...


一、經緯度表示方式

    MongoDB 中對經緯度的存儲有著自己的一套規範(主要是為了可以在該欄位上建立地理空間索引)。包括兩種方式,分別是 Legacy Coordinate Pairs (這個詞實在不知道怎麼翻譯...) 和  GeoJSON 。

  • Legacy Coordinate Pairs

Legacy Coordinate Pairs 又有兩種方式可以存儲經緯度,可以使用數組(首選)或嵌入式文檔。

數組:

<field>: [<longitude>, <latitude> ]

嵌入式文檔:

<field>: { <field1>: <longitude>, <field2>: <latitude> }

tips:有效經度值介於-180和180之間。有效緯度值介於-90和90之間。

  • GeoJSON

GeoJson 比 Legacy Coordinate Pairs 要強大的多,Legacy Coordinate Pairs 僅僅用來保存一個經緯度,而 GeoJson 可以用來指定點、線和多邊形。

點可以用形如[longitude, latitude]([經度,緯度])的兩個元素的數組表示:

{
"geometry": {
        "type": "Point",
        "coordinates": [125.6, 10.1]
   }
}

線可以用一個由點組成的數組來表示:

{
"geometry": {
        "type": "LineString",
         "coordinates": [[125.6, 10.1],[125.6,10.2],[125.6,10.3]]
   }
}

多邊形的表示方式與線一樣(都是一個由點組成的數組),但是"type"不同:

{
"geometry": {
        "type": "Polygon",
         "coordinates": [[125.6, 10.1],[125.5,10.2],[125.7,10.3]]
  }
}

type 除了 Point(點)、LineString(線)、Polygon(多邊形),還有 MultiPoint(多點)、MultiLineString(多個線) 和  MultiPolygon(多個多邊形)。

"geometry"欄位的名字可以是任意的,但是其中的子對象是由GeoJSON指定的,不能改變。

二、地理空間索引

  • 2dsphere索引

2dsphere索引用於地球錶面類型的地圖,允許使用在 Legacy Coordinate Pairs 保存的經緯度欄位上和使用GeoJSON格式保存的點、線和多邊形欄位上。

  db.world.ensureIndex({"geometry" : "2dsphere"})
  • 2d索引

 對於非球面地圖(游戲地圖、時間連續的數據等),可以使用"2d"索引代替"2dsphere"。

 2d 索引 僅允許使用在 Legacy Coordinate Pairs 保存的經緯度欄位上。

  db.world.ensureIndex({"geometry" : "2d"})
  • 區別:

2dsphere索引只支持球形查詢(即球面上幾何圖形的查詢)。

2d索引支持平面查詢(即在平面上幾何圖形的查詢)和一些球形查詢。雖然2d索引支持一些球形查詢,但是對這些球形查詢使用2d索引可能會導致錯誤,例如極點附近會出現大量的扭曲變形。
2d索引只能對點進行索引。可以保存一個由點組成的數組,但是它只會被保存為由點組成的數組,不會被當成線。特別是對於"$geoWithin"查詢來說,這是一項重要的區別。如果將街道保存為由點組成的數組,那麼如果其中的某個點位於給定的形狀之內,這個文檔就會與$geoWithin相匹配。但是,由這些點組成的線並不一定完全包含在這個形狀之內。

三、地理空間查詢

    可以使用多種不同類型的地理空間查詢:交集(intersection)、包含(within)以及接近(nearness)。

  • $geoIntersects

定義:指出與查詢位置相交的文檔。

支持的索引:2dsphere

幾何操作符:

    1. $geometry (僅支持 2dsphere 索引,指定GeoJSON格式的幾何圖形)
  • $geoWithin

定義:指出完全包含在某個區域的文檔。

支持的索引:2dsphere、2d

幾何操作符:

  1. $box(僅支持 2d 索引,查詢出矩形範圍內的所有文檔)
  2. $center(僅支持 2d 索引,查詢出圓形範圍內的所有文檔)
  3. $polygon (僅支持 2d 索引,查詢出多邊形範圍內的所有文檔)
  4. $centerSphere(支持 2d 索引和 2dsphere 索引,查詢出球面圓形範圍內的所有文檔)
  5. $geometry (僅支持 2dsphere 索引,指定GeoJSON格式的幾何圖形)
  • $near

定義:指出與查詢位置從最近到最遠的文檔。

支持的索引:2dsphere、2d

幾何操作符:

  1. $maxDistance (支持 2dsphere 索引和 2d 索引,指定查詢結果的最大距離)
  2. $minDistance (僅支持 2dsphere 索引,指定查詢結果的最小距離)
  3. $geometry (僅支持 2dsphere 索引,指定GeoJSON格式的點)

備註:$minDistance 官方文檔說僅支持 2dsphere 索引,但是我實踐證明 $minDistance 也支持 2d 索引,大家可以試試看,這裡保留爭議。

  • $nearSphere

定義:使用球面幾何計算近球面的距離,指出與查詢位置從最近到最遠的文檔。

支持的索引:2dsphere、2d

幾何操作符:

  1. $maxDistance (支持 2dsphere 索引和 2d 索引,指定查詢結果的最大距離)
  2. $minDistance (僅支持 2dsphere 索引,指定查詢結果的最小距離)
  3. $geometry (僅支持 2dsphere 索引,指定GeoJSON格式的點)

備註:$minDistance 官方文檔說僅支持 2dsphere 索引,但是我實踐證明 $minDistance 也支持 2d 索引,大家可以試試看,這裡保留爭議。

四、實踐

  • "$geoIntersects" 操作符找出與查詢位置相交的文檔 ?
db.driverPoint.find(
   {
     coordinate: {
       $geoIntersects: {
          $geometry: {
             type: "Polygon" ,
             coordinates: [
               [ [ 118.193828, 24.492242 ], [ 118.193953, 24.702114 ], [ 118.19387, 24.592242 ],[ 118.193828, 24.492242 ]]
             ]
          }
       }
     }
   }
)
View Code

 tips:coordinates 表示多邊形,第一個點 和 最後一個點 必須相同,因為這樣才能拼成一個對邊形呀!

 

  • "$geoWithin"操作符找出完全包含在某個區域的文檔?
db.driverPoint.find(
   {
     coordinate: {
       $geoWithin: {
          $geometry: {
             type: "Polygon" ,
             coordinates: [
               [ [ 118.193828, 24.492242 ], [ 118.193953, 24.702114 ], [ 119.19387, 28.792242 ],[ 118.193828, 24.492242 ]]
             ]
          }
       }
     }
   }
)
View Code
  • "$geoWithin"操作符找出矩形範圍內的文檔?
db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
        $box: [
          [ 118.0,24.0 ],
          [ 120.0,30.0 ]
        ]
     }
  }
}
)
View Code

 tips:"$box"接受一個兩元素的數組:第一個元素指定左下角的坐標,第二個元素指定右上角的坐標。

  • "$geoWithin"操作符找出圓形範圍內的文檔?
db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
         $center: [ [ 118.067678, 24.444373] , 10 ] 
     }
  }
}
)
View Code

tips:"$center"接受一個兩元素數組作為參數:第一個元素是一個點,用於指定圓心;第二個參數用於指定半徑。

  • "$geoWithin"操作符找出多邊形範圍內的文檔?
db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
         $polygon: [ [ 118.067678 , 24.444373 ], [ 119.067678 , 25.444373 ], [ 120.067678 , 26.444373 ] ]
     }
  }
}
)
View Code

tips"$polygon" 列表中的最後一個點會被連接到第一個點,以便組成多邊形。

 

  • "$geoWithin"操作符找出球面圓形範圍內的文檔?
db.driverPoint.find(
{
  coordinate: {
     $geoWithin: {
         $centerSphere: [ [ 118.067678, 24.444373 ], 10/3963.2 ]
     }
  }
}
)
View Code

tips:該例子表示 距離 [118.067678, 24.444373] 中心點10 英里範圍內的所有文檔,查詢通過除以地球的大約赤道半徑(3963.2英里)將距離轉換為弧度。

 

  • $near 找出距離一個點相應距離內的文檔?

geoJson 格式(僅支持 2dsphere 索引):

db.driverPoint.find(
{
   coordinate: {
     $near: {
       $geometry: {
          type: "Point" ,
          coordinates: [ 118.067678 , 24.444373 ]
       },
       $maxDistance: 3000,
       $minDistance: 0
     }
   }
}
)
View Code

Legacy Coordinate Pairs 格式(僅支持 2d 索引):

db.driverPoint.find(
{
   coordinate: {
     $near: [ 118.193828 , 24.492242 ],
     $maxDistance: 0.10
     }
}
)
View Code

tips:1、$near 當用 geoJson 格式表示時打完, 距離單位是米(meter)。

         2、$near 當用 Legacy Coordinate Pairs 格式表示時,距離單位是弧度(radian)。  

         3、"$near"是唯一一個會對查詢結果進行自動排序的地理空間操作符:"$near"的返回結果是按照距離由近及遠排序的。

五、結語

    怎麼說呢?學習這方面的知識老是給我一種特別亂的感覺。稍微總結下吧!MongoDB 對於地理空間的查詢 是基於 它對 地理空間的索引(即2dsphere 和 2d)來實現的。所以,我們只要搞清楚什麼時候 該建立 2dsphere 索引,什麼時候該建立 2d 索引,然後再找適用於該索引的操作符就很清晰明瞭了!總之,geoJSON 格式保存的經緯度一定 建立 2dsphere 索引。Legacy Coordinate Pairs 格式保存的經緯度 僅在表示 平面地圖的時候才考慮建立 2d 索引,其他情況還是選擇 2dsphere 索引。

    Spring Data MongoDB 中對地理位置的查詢可參考 https://github.com/JMCuixy/SpringDataMongoDB 中單元測試的 Test03.java。

 

 

參考資料:

1、《MongoDB 權威指南第二版》

2、https://docs.mongodb.com/manual/reference/operator/query-geospatial/


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文內容: 什麼是視圖 創建視圖 查看視圖 視圖的修改 視圖的刪除 視圖的數據操作 首發日期:2018-04-13 什麼是視圖: 視圖是一種基於查詢結果的虛擬表,數據來源的表稱為基本表。 視圖的建立和刪除不影響基本表。 視圖的插入,修改操作會影響基本表。 如果視圖來自多個基本表,那麼不可以修改基本表... ...
  • 今天,正在開心的寫著代碼,突然多個人員反饋網站特別慢。 總結:一開始這個項目已經正常跑了一段時間了,不知道為什麼會突然出現這個問題。沒有深究,有知道的歡迎留言。 ...
  • https://www.cnblogs.com/xqzt/p/4482888.html ...
  • [20180413]熱備模式相關問題2.txt--//上午測試熱備模式相關問題,就是如果打開熱備模式,如果中間的歸檔丟失,oracle在alter database end backup ;時並沒有應用日誌.--//雖然熱備份模式文件頭scn被"凍結",一定在某個地方記錄的檢查點的scn,這樣在執行 ...
  • 業務量增長到一定程度後,簡單的主從架構已經不能滿足業務需要,主庫的讀寫壓力增大,逐漸達到瓶頸,這時引入主從讀寫分離是一個不錯的選擇。本文介紹了實現讀寫分離的一款工具---Amoeba。 ...
  • net start mysql 無法啟動 1.可以進入MySQL的bin目錄下 mysql --remove 2.檢查一下自己的my.ini是否配置正確 [mysqld] #basedir代表自己MySQL的安裝根目錄basedir = D:\MySQL\mysql-5.7 #datadir代表自己 ...
  • 一、概要參考:https://docs.mongodb.com/getting-started/python/client/pymongo是python操作mongodb數據的第三方模塊,官方推薦使用;使用pymongo之前,首先安裝pymongo模塊,命令如下(使用pip安裝):pip insta... ...
  • [201804012]關於hugepages 3.txt--//有一段時間我一直強調安裝oracle一定要配置hugepage,因為現在的伺服器記憶體越來越大,如果還使用4K的頁面表,如果記憶體表占用記憶體巨大,--//特別連接數量很大的情況下,更加明顯,結果導致記憶體緊張,使用交換,這些類似的例子網上很多 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...