簡介
隨著近幾年各類移動終端的迅速普及,基於地理位置的服務(LBS)和相關應用也越來越多,而支撐這些應 用的最基礎技術之一,就是基於地理位置信息的處理。我所在的項目也正從事相關系統的開發,我們使用的是 Symfony2+Doctrine2 ODM+MongoDB的組合。
我們將這些技術要點整理成文,希望能夠通過本文的介紹和案例,詳細 解釋如何使用MongoDB進行地理位置信息的查詢和處理。在文章的開頭,我們也會先介紹一下業界通常用來處理地理位置信 息的一些方案並進行比較,讓讀者逐步了解使用MongoDB查詢及處理地理位置信息的優勢。
本文使用了Symfony2和 Doctrine2作為Web應用的開發框架,對於想了解Symfony2的數據庫操作的讀者來說閱讀本文也可以了解和掌握相關的技術和 使用方法。
1. LBS類應用特點
不管是什麼LBS應用,一個共同的特點就是:他們的數據都或多或少包含了地 理位置信息。而如何對這些信息進行查詢、處理、分析,也就成為了支撐LBS應用的最基礎也是最關鍵的技術問題。
而由於地理位置信息的特殊性,在開發中經常會有比較難以處理的問題出現,比如:由於用戶所在位置的不固定性,用戶可 能會在很小范圍內移動,而此時經緯度值也會隨之變化;甚至在同一個位置,通過GPS設備獲取到的位置信息也可能不一樣 。所以如果通過經緯度去獲取周邊信息時,就很難像傳統數據庫那樣做查詢並進行緩存。
對於這個問題,有讀者可 能會說有別的處理方案,沒錯,比如只按經緯度固定的幾位小數點做索引,比如按矩陣將用戶劃分到某固定小范圍的區域( 可以參考後文將會提到的geohash)等方式,雖然可以繞個彎子解決,但或多或少操作起來比較麻煩,也會犧牲一些精度, 甚至無法做到性能的最優化,所以不能算作是最佳的解決辦法。
而最近幾年,直接支持地理位置操作的數據庫層出 不窮,其操作友好、性能高的特性也開始被我們慢慢重視起來,其中的佼佼者當屬MongoDB。
MongoDB在地理位置信 息的處理上有什麼優勢?下面我們通過一個簡單的案例來對比一下各種技術方案之間進行進行地理位置信息處理的差異。
2. 幾個地理位置信息處理方案的對比和分析
1. 確定功能需求
對於任何LBS應用來說,讓用戶尋找周 圍的好友可能都是一個必不可少的功能,我們就以這個功能為例,來看看各種處理方案之間的差異和區別。
我們假 設有如下功能需求:
顯示我附近的人
由近到遠排序
顯示距離
2. 可能的技術方案
排除一些不通用和難以實現的技術,我們羅列出以下幾種方案:
基於MySQL數據庫
采用GeoHash索引,基於MySQL
MySQL空間存儲(MySQL Spatial Extensions)
使用MongoDB存儲地理位置信息
我們一個個來分析這幾種方案。
方案1:基於MySQL數據庫
MySQL的使用非常簡單。對於大部分已經使用 MySQL的網站來說,使用這種方案沒有任何遷移和部署成本。
而在MySQL中查詢“最近的人”也僅需一條SQL即 可,
SELECT id, ( 6371 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians ( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance FROM places HAVING distance < 25 ORDER BY distance LIMIT 0 , 100;
注:這條SQL查詢的是在lat,lng這 個坐標附近的目標,並且按距離正序排列,SQL中的distance單位為公裡。
但使用SQL語句進行查詢的缺點也顯而易 見,每條SQL的計算量都會非常大,性能將會是嚴重的問題。
先別放棄,我們嘗試對這條SQL做一些優化。
可 以將圓形區域抽象為正方形,如下圖