2013年9月17日 星期二

使用MongoDB做地理位置查詢(簡易版)

因為智慧型手機的普及,LBS(Location Based Service) 的服務在近期還算是蠻夯的服務,例如找附近的人,找附近的店家,找附近的大眾運輸工具...等等之類的在地化服務,若要將這類的服務資料查詢做在 MySQL ,對於資料庫來說是相當沉重的負擔,因為要服務的使用者每次位置座標皆不相同,所以要查詢的每個標的與使用者的距離也不相同,所以每次的查詢就要針對資料庫的的所有資料去做運算,或是限制要查詢資料的座標範圍以減少查詢計算的資料量,像是只找台北的標的資料,可是這樣的資料量還是相當龐大的,如果有 10 萬 筆資料要做查詢計算, 100 個 使用者做查詢就需要對 1000 萬筆(100 * 100000) 資料做查詢計算,這對於資料庫的運算是一個很大的負擔,而 MongoDB 有提供這類地理查詢的方法及優化。

使用 $near 做地理位置查詢

建立測試資料(以台北捷運為例)

我們在MongoDB建立捷運台北車站附近的捷運站座標資料,另外加入建立時間資料,我們會想要除了做地理位置搜尋,搜尋出來的資料還可以依照時間做排序。

建立地理位置索引


查詢捷運台北車站附近的捷運站


找捷運台北車站附近距離2公里內的捷運站


這裡會列出距離台北車站2公里以內的所有捷運站資料,使用 $near 計算出來的距離單位為經緯度度數單位,我們要將單位換算成公里則需要除以111.12

(6371公里(地球半徑)* 3.14 (圓周率) / 180(半圓度數) = 111.19492664456)

若需要將單位換成英里則需要除以69.1

(3959英里(地球半徑)* 3.14 (圓周率) / 180(半圓度數) =69.097585086456)


找捷運台北車站附近距離2公里內的捷運站、依照建立時間做排序

除了找出距離內的捷運車站資料,我們還希望依照資料建立的時間做排序


找捷運台北車站附近距離2公里內的捷運站、依照建立時間做排序、找前3筆資料

如果我們要將排序後的資料做分頁資料顯示的話,我們則會限制資料筆數


在這裡你會發現,做資料筆數的限制撈出來的資料不是符合我們的預期的資料


因為當你在使用limit去做資料筆數的限制時,MongoDB 的作法撈取距離最近的筆數資料,撈出來後再做時間的排序,所以才會看到這樣的結果。

備註


MongoDB 可以對查詢的結果再做子查詢,我有試著先撈出距離2公里內,且依照時間排序後的資料,然後再對其做資料筆數限制的子查詢,可是結果與上述相同:


如果要使用 MongoDB 做 LBS 查詢時,也能正確的對資料做排序及分頁,可以再參考"使用MongoDB做地理位置查詢(進階版)"一文的說明。





參考資料

沒有留言:

張貼留言

ADS