redis提供了地理位置信息(geo)功能,有了他就可以完成附近的人、搖一搖等功能。首先,介紹下geo的相關api。
GEO API
添加地址位置信息
geoadd key longitude latitude member [longitude latitude member …]
-
longitude :經度
-
latitude :緯度
-
member :成員
該命令可以一次添加一個或多個成員
有一些用戶,都在合肥,現在把他們的地理坐標都存放在redis里。
-
小A在家里看電視,他家的坐標為:117.230279,31.81676
-
小B在公司加班,公司的坐標為:117.229704,31.824676
-
小C在出差,他出差的地址坐標為:117.300419,31.696095
-
小D在家?guī)蓿业牡刂纷鴺藶椋?17.192909,31.732465
-
小E還在上學,他學校地址坐標為:117.189604,31.838297
127.0.0.1:6379>?geoadd?location?117.230279?31.81676?a?117.229704?31.824676?b (integer)?2 127.0.0.1:6379>?geoadd?location?117.300419?31.696095?c (integer)?1 127.0.0.1:6379>?geoadd?location?117.192909?31.732465?d (integer)?1 127.0.0.1:6379>?geoadd?location?117.189604?31.838297?e (integer)?1
獲取兩個地點的距離
geodist key member1 member2 [unit]
unit有四個單位
-
‘m’ => 米
-
‘km’ => 千米
-
‘mi’ => 英里
-
‘ft’ => 尺
我們主要會用到米以及千米。
現在我們來看看小A和小B之間的距離
127.0.0.1:6379>?GEODIST?location?a?b?km "0.8821"
可以看到小A和小B之間有0.88千米
再來看看小C和小E之間的距離
127.0.0.1:6379>?GEODIST?location?c?e?km "18.9728"
他們之間相差將近19千米。
獲取地址位置信息
geopos key member [member …]
來看下小D的所在地址的經緯度信息
127.0.0.1:6379>?geopos?location?d 1)?1)?"117.19290822744369507" ???2)?"31.73246441933707018"
獲取指定位置范圍內的地理信息位置集合
georadius key longitude latitude radiusm km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key] [storedist key] georadiusbymember key member radiusm km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key] [storedist key]
這兩個命令相比其他的稍顯復雜。我們一起來看看這兩個命令。
這兩個命令功能基本相似,主要的區(qū)別是,第一個命令給出的是具體的經緯度,而第二個命令則只給出了成員名。比如,我想知道成員離合肥大蜀山的距離,因為大蜀山經緯度信息還沒有存放在redis中,所以,我們就需要用第一條命令,將大蜀山的經緯度輸入即可。又如,其他成員離小A所在坐標的距離,那么就可以使用第二條命令,直接輸入成員小A即可。
radiusm 及后面的單位是必填信息,指定在半徑距離多少范圍內搜索。
合肥大蜀山的坐標是117.175571,31.846746
#?查看離大蜀山10km的成員有哪些 127.0.0.1:6379>?GEORADIUS?location?117.175571?31.846746?10?km 1)?"e" 2)?"a" 3)?"b"
可以看到小e、小a及小b離大蜀山比較近,在10km內。
WITHCOORD: 將位置元素的經度和維度也一并返回
127.0.0.1:6379>?GEORADIUS?location?117.175571?31.846746?10?km?withcoord 1)?1)?"e" ???2)?1)?"117.18960374593734741" ??????2)?"31.83829663190295634" 2)?1)?"a" ???2)?1)?"117.23027676343917847" ??????2)?"31.81675910621205361" 3)?1)?"b" ???2)?1)?"117.22970277070999146" ??????2)?"31.8246750403926697"
可以看到,除了給出了成員外,成員的位置信息頁一并給出了
withdist:返回結果中包含離中心節(jié)點位置的距離
127.0.0.1:6379>?GEORADIUS?location?117.175571?31.846746?10?km?withcoord?withdist 1)?1)?"e" ???2)?"1.6252" ???3)?1)?"117.18960374593734741" ??????2)?"31.83829663190295634" 2)?1)?"a" ???2)?"6.1522" ???3)?1)?"117.23027676343917847" ??????2)?"31.81675910621205361" 3)?1)?"b" ???2)?"5.6737" ???3)?1)?"117.22970277070999146" ??????2)?"31.8246750403926697"
可以看到小E離大蜀山1.62千米,小A離大蜀山6.15千米,小B離大蜀山5.67千米。
withhash:這個命令可以忽略不看,基本用不上
COUNT count:指定返回結果的數量。
asc|desc:返回結果按照離中心節(jié)點的距離做升序或者降序。
storedist key:將返回結果離中心節(jié)點的距離保存到指定鍵。
#?獲取離大蜀山100km內范圍的成員,按距離的升序,只需給出最近的4個成員即可 127.0.0.1:6379>?GEORADIUS?location?117.175571?31.846746?100?km?withdist?count?4?asc 1)?1)?"e" ???2)?"1.6252" 2)?1)?"b" ???2)?"5.6737" 3)?1)?"a" ???2)?"6.1522" 4)?1)?"d" ???2)?"12.8164"
實戰(zhàn)
介紹完了上面知識后,就可以來使用php結合redis完成搖一搖找附近的人的功能了。首先,把成員的位置信息給保存下來。
偽代碼如下:
function?addLocation?($key,$member,?$lng,?$lat) { ????$redis->geoadd($key,?$lng,?$lat,?$member); }
然后,獲取附近的人的信息
function?near?( ????$key,? ????$member,? ????$radius,? ????$unit?=?'km',? ????$count?=?0,?? ????$withDist?=?false,? ????$withcoord?=?false,? ????$orderby?=?'ASC' ) { ????$redis?=?new?Redis(); ????$redis->connect('localhost',?6379); ????$options?=?[$orderby]; ????if?($count?>?0)?{ ????????$options['count']?=?$count; ????} ????if?($withDist)?{ ????????$options[]?=?'WITHDIST'; ????} ????if?($withcoord)?{ ????????$options[]?=?'WITHCOORD'; ????} ????$result?=?$redis->geoRadiusByMember($key,?$member,?$radius,?$unit,?$options); ????return?$result; }
使用redis可以大大方便開發(fā)人員,豐富的API可以完成各種各樣的需求,Redis的使用已經成為程序員必備的技能了。