您好,登錄后才能下訂單哦!
附近的人:
地圖元素的位置數據使用二維的經緯度表示,經度范圍 (-180, 180],緯度范圍 (-90, 90],緯度正負以赤道為界,北正南負,經度正負以本初子午線 (英國格林尼治天文臺) 為界,東正西負。比如掘金辦公室在望京 SOHO,它的經緯度坐標是 (116.48105,39.996794),都是正數,因為中國位于東北半球。
當兩個元素的距離不是很遠時,可以直接使用勾股定理就能算得元素之間的距離。我們平時使用的「附近的人」的功能,元素距離都不是很大,勾股定理算距離足矣。不過需要注意的是,經緯度坐標的密度不一樣 (地球是一個橢圓),勾股定律計算平方差時之后再求和時,需要按一定的系數比加權求和,如果不求精確的話,也可以不必加權。
如果現在元素的經緯度坐標使用關系數據庫 (元素 id, 經度 x, 緯度 y) 存儲,你該如何計算?
首先,你不可能通過遍歷來計算所有的元素和目標元素的距離然后再進行排序,這個計算量太大了,性能指標肯定無法滿足。一般的方法都是通過矩形區域來限定元素的數量,然后對區域內的元素進行全量距離計算再排序。這樣可以明顯減少計算量。如何劃分矩形區域呢?可以指定一個半徑 r,使用一條 SQL 就可以圈出來。當用戶對篩出來的結果不滿意,那就擴大半徑繼續篩選。
select id from positions where x0-r < x < x0+r and y0-r < y < y0+r
為了滿足高性能的矩形區域算法,數據表需要在經緯度坐標加上雙向復合索引 (x, y),這樣可以最大優化查詢性能。
但是數據庫查詢性能畢竟有限,如果「附近的人」查詢請求非常多,在高并發場合,這可能并不是一個很好的方案。
業界比較通用的地理位置距離排序算法是 GeoHash 算法,Redis 也使用 GeoHash 算法。GeoHash 算法將二維的經緯度數據映射到一維的整數,這樣所有的元素都將在掛載到一條線上,距離靠近的二維坐標映射到一維后的點之間距離也會很接近。當我們想要計算「附近的人時」,首先將目標位置映射到這條線上,然后在這個一維的線上獲取附近的點就行了。
Redis 的 Geo 指令基本使用
geoadd 指令攜帶集合名稱以及多個經緯度名稱三元組,注意這里可以加入多個三元組
127.0.0.1:6379> geoadd company 116.48105 39.996794 juejin
距離
geodist 指令可以用來計算兩個元素之間的距離,攜帶集合名稱、2 個名稱和距離單位。
127.0.0.1:6379> geodist company juejin ireader km
獲取元素位置
geopos 指令可以獲取集合中任意元素的經緯度坐標,可以一次獲取多個。
127.0.0.1:6379> geopos company juejin
獲取元素的 hash 值
geohash 可以獲取元素的經緯度編碼字符串,上面已經提到,它是 base32 編碼。 你可以使用這個編碼值去 geohash.org/${hash}中進行直… geohash 的標準編碼值。
127.0.0.1:6379> geohash company ireader
http://geohash.org/
附近的公司
georadiusbymember 指令是最為關鍵的指令,它可以用來查詢指定元素附近的其它元素,它的參數非常復雜。
127.0.0.1:6379> georadiusbymember company ireader 20 km count 3 asc
http://researchlab.github.io/2018/10/06/redis-09-geohash/
以上內容來自老錢的redis深度歷險,好像現在紙質版也出了。大家可以購買。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。