搜索附近的人代碼
關注:13 發布時間:2021-11-12 09:13:04
老板突然想上網找一個離方圓一公里的商業代理。明天上線!接到這個要求的時候差點吐血,時間太緊了。趕緊查查相關技術選型。經過很多麻煩,終于在晚上10點滿足了這個需求,現在總結一下實現的大致思路。
2.mysql不適合
在滿足需求的時候,首先要考慮現有的東西能不能滿足,代價是什么。
我首先想到的是mysql。畢竟,大部分數據應該堅持到mysql.然而,使用mysql需要geohash.的自我計算。需要使用大量的數學和幾何計算,并需要學習地理相關知識。門檻高,短時間內不可能完成要求。從長遠來看,這不是mysql擅長的領域,因此不予考慮。
geohash可以參考其他文獻
2.redis中的地球同步軌道
redis是比較熟悉的k-v數據庫,它經常被用作高性能緩存數據庫,并將在大多數項目中使用。自3.2版本以來,它提供了geo能力,用于實現附近位置、距離計算等依賴于地理位置信息的功能。geo"s的相關命令如下:
redis命令描述geohash返回一個或多個位置元素的geohash,這意味著geopos從key返回所有給定位置元素的位置(經度和緯度)。geodist返回兩個給定位置之間的距離。地球位于給定的緯度和經度的中心。找出一定半徑內的元素geoadd將指定的地理空間位置(緯度、經度、名稱)添加到指定的關鍵georadiusbymember找出指定范圍內的元素,中心點由給定的位置元素確定
redis會假設地球是一個完美的球體,所以可能會有一些位置計算偏差,據說是=0.5%。對于地理位置要求嚴格的需求,要進行一些場景測試,測試是否能滿足需求。
2.1寫地理信息
那么如何實現目標單位半徑內的所有元素呢?我們可以將所有位置的經緯度轉換成52位的geohash,通過上表中的geoadd寫入redis。
命令格式:
geoadd關鍵經度緯度成員[經度緯度成員…]
相應的例子:
redis geo add cities : locs 117.12 39.08天津114.29 38.02石家莊
(整數)2
意思是在key.個城市的sorted set集合中添加經度為117.12、緯度為39.08的天津和經度為114.29、緯度為38.02的石家莊,您可以添加一個或多個位置。然后我們可以使用其他命令來計算地理位置。
有效經度范圍從-180度到180度。有效緯度范圍從-85.05112878度到85.0512778度。當坐標位置超過上述指定范圍時,該命令將返回一個錯誤。
2.2統計單位半徑內的面積
借助georadius,我們可以找到給定經緯度的某個半徑內的所有元素。
命令格式:
地理坐標長緯度半徑m | km | ft | mi[withourd][withdist][with ash][count][asc | desc]
這個命令比geoadd更復雜:
radius半徑長度,必需。以下m、km、ft和mi是長度單位選項,四選一。
withcoord返回位置元素的經度和維度,這是可選的。
withdist返回位置元素和中心點以及位置元素之間的距離。距離的單位與查詢單位相同,這不是必需的。
withhash以52位精度返回位置的geohash值,這是可選的。反正我很少用這個。也許其他一些偏向底層的lbs應用服務需要這個。
count返回合格位置元素的數量,這不是必需的。比如返回前10名,這樣可以避免過多的一致結果帶來的性能問題。
asc|desc排序方式,非必選。默認情況下返回未排序,但是大多數我們需要進行排序。參照中心位置,從近到遠使用asc,從遠到近使用desc。
例如,我們在城市:locs中查找以(115.03,38.44)為中心,方圓200公里的城市,結果包含城市名稱、對應的坐標和距離中心點的距離(公里),并按照從近到遠排列。命令如下:
redis georadius city : locas 115.03 38.44 200km,帶coord witist asc
1) 1)石家莊
2) "79.7653"
3) 1) "114.29000169038772583"
2) "38.01999994251037407"
2) 1)"天津"
2) "186.6937"
3) 1) "117.02000230550765991"
2) "39.0800000535766543"
你可以加上計數一來查找比較近的一個位置。
3.基于redis geo實戰
大致的原理思路說完了,接下來就是實操了。結合spring boot應用我們應該如何做?
3.1 開發環境
需要具有geo特性的redis版本,這里我使用的是redis 4。另外我們客戶端使用spring-boot-starter-data-redis。這里我們會使用到使用對象。
3.2 批量添加位置信息
第一步,我們需要將位置數據初始化到redis中。在spring data redis中一個位置坐標(液化天然氣,lat)可以封裝到org。spring框架。數據。geo。要點對象中。然后指定一個名稱,就組成了一個位置geo信息redistemplate。提供了批量添加位置信息的方法。我們可以將章節2.1中的添加命令轉換為下面的代碼:
mapstring,point points=new hashmap;
points.put("天津",new point(117.12,39.08));
points.put("石家莊",新點(114.29,38.02));
//redistemplate批量添加長狹潮道
redis模板。邊界城市:個位置.添加(分);
可以結合彈簧靴提供的applicationrunner接口來實現初始化,建議從mysql等數據庫同步地理信息。
@豆
public applicationrunner cache activeapprunner(redistemplate string,string redistemplate) {
返回參數- {
比較終字符串geo _ key=" cities:locs
//清理緩存
redistemplate。刪除(geo _ key);
//建議從關系型數據庫同步地理信息
mapstring,point points=new hashmap;
points.put("天津",new point(117.12,39.08));
points.put("石家莊",新點(114.29,38.02));
//redistemplate批量添加地理定位
boundgeooperationsstring,string geoops=redistemplate。boundgeoops(geo _ key);
geoops.add(點);
};
}
3.3 查詢附近的特定位置
使用針對georadius命令也有封裝:
地理位置半徑(k鍵,內圓,地理坐標標準參數)
圓對象是封裝覆蓋的面積(圖1),需要的要素為中心點坐標要點對象、半徑(半徑)、計量單位(公制),例如:
點點=新點(115.03,38.44);
公制公制=redisgeocommands .距離單位。kumts
距離距離=新距離(200,公制);
圓圓=新圓(點,距離);
地理標準用來封裝georadius的一些可選命令參數,參見章節2.2中的帶門、計數、asc等,例如我們需要在返回結果中包含坐標、中心距離、由近到遠排序的前5條數據:
redisgeocommands .地理社區標準參數=地理社區。地理標準。newgeoradiusargs。includedistance。包括坐標。排序排序。極限(限制);
然后執行半徑方法就會拿到georesultsredisgeocommands .地理位置字符串封裝的結果,我們對這個可迭代對象進行解析就可以拿到我們想要的數據:
georesultsredisgeocommands .geolocationstring radius=redis template。opsforgeo。半徑(geo_stage,圓,args);
if (radius!=) {
list staged to staged tos=new arraylist;
半徑。foreach(地理定位地理結果-->
重新調用命令地理位置字符串內容=地理位置
georesult . getcontent;
//成員姓名如天津
string name=content . getname;
//對應的經緯度坐標
point pos=content . getpoint;
//到中心點的距離
distance dis=geolocationgeoresult . getdistance;
});
}
3.4刪除元素
有時我們可能需要刪除位置元素,但是redis的geo沒有刪除成員的命令。但是因為它的底層是zset,我們可以借助zrem命令刪除,對應的java代碼是:
redistemplate . boundsetops(geo _ stage)。移除(“天津”);
4.摘要
,我們使用redis"sgeo功能來實現附近常見的地理信息查詢需求,簡單易用。事實上,nosql,的另一個mongodb數據庫,也可以使用。在數據量較小的情況下,redis能夠很好地滿足需求。如果數據量大,可以用mongodb.來實現,本文涉及的demo可以通過文末相關文章的鏈接來獲得。
猜你喜歡
-
日本當年為什么攻打珍珠港?80人支持
二戰初期,美國遠離主戰場,所以大陸沒有受到戰爭的影響,美國人民過著相對穩定的生活。然而,日本毫無征兆地轟炸了美國的珍珠港,使美國卷入了一場殘酷的戰爭。日本為什么要這么做?主…
-
支付寶可以薅的羊毛23人支持
這篇文章是一個失敗的薅羊毛戰略,但我不想讓我努力工作的戰略付諸東流。發出去!如果能幫助無意看這篇文章的人避坑呢?支付寶-財富有相關活動嗎?像前幾天一樣,畫了15.18元。(是超…
-
拼多多出事改簡介?58人支持
近日,拼多多一名員工因過度勞累死亡,在網上引起軒然大波。消息稱,死亡女孩已火化,相關后續治療仍在進一步協調中。事件發生后,平臺在某平臺上進行了動態開發。動態內容一般表示現…
-
為什么不建議年輕人一直刷抖音?45人支持
作為目前短視頻的主流平臺,tik tok每天有6億用戶,可以說是全民的tik tok。從70、80年代到三、四歲的孩子,tik tok是慣的。雖然是社會的發展,科技的進步,但我個人覺得這不是一…
-
直接讓微信語音變聲的25人支持
眾所周知,qq有自己的語音變聲,不需要編輯就可以發送。都是老馬產品,微信沒有這么好玩的功能。我也表示無奈。然而今天,陶濤給了每個人分享一個手機聊天變聲的技巧,和叔叔可以在…
-
函授和網絡教育有什么區別93人支持
如果我們一直在大?;蚋偷慕逃?,我們會不斷失去更多的信心,然后在職業發展的過程中不斷抑郁。為了使我們能夠更快地進入社會并找到一份穩定的工作,教育是必不可少的。對于…
-
互聯網上神秘的一群人:羊毛黨13人支持
大家好,我是網購的先鋒。今天,我們來談談“羊毛黨”。相信大家都聽說過羊毛黨這個詞,但是不清楚他們在做什么。大環境的形成據統計,現在的網購會員大約有6.39億。由于互聯網的快…
-
抖音注銷后是什么狀態116人支持
今天是全新的一天,11月的第一天,還有61天進入2021年。今天的自己很不一樣,沒有過去的頹廢,心里有一絲期待。今天,tik tok的帳戶被取消,同時卸載。我從17年開始接觸tik tok,3年多…
-
股票停牌是好是壞51人支持
停牌通常是由于一些市場消息或上市公司想發布的最大事件。為了維護投資市場的公平正義原則,證券交易所采取了突然停牌的方式。大多數情況下,上市公司停牌是在收盤后的晚上宣布…
-
浪花黑卡怎么使用?37人支持
微信和支付寶可以說是兩個“國貨軟件”,在中國大約有11億用戶。支付寶先后推出了花店和貸店,受到大家的歡迎。對于很多微信用戶來說,他們希望微信也能推出類似支付寶的花店、借…
-
無理數包括哪些34人支持
什么是無理數?很多學生在接觸無理數時不知所措,有時會讓人感到頭疼。今天極客數學團隊整理了關于無理數的知識點和相關練習。我們來看看什么是無理數。1.什么是無理數?無理數是…
-
失敗了的羅永浩73人支持
這段時間一直被羅永浩的各種消息所席卷。此人一直站在商業領域的最前沿,從錘子手機到玩電子煙,業務不斷失敗?,F在不僅欠了一筆債,還被丹陽市人民法院列入失信人黑名單,限制高消…
熱門十大品牌
- 2021年我國十大黃金品牌排行榜31000人
- 眼鏡品牌十大排行榜前10名26362人
- 十大證券公司排行榜前10名23243人
- 2021年我國雜志排行榜前10名20055人
- 我國十大雜志排行榜前10名16359人
- 2021我國十個宜居城市排行榜前11487人
- 男士褲子品牌十大排行榜前10名11186人
- 2021十大火熱電腦游戲排行榜前11057人
- 十大衛生巾品牌排行榜前十名8848人
- 我國十大襪子品牌排行榜前十名8372人