產(chǎn)品功能解讀:「附近的人」是按什么規(guī)則計(jì)算的

8 評(píng)論 14616 瀏覽 67 收藏 10 分鐘

距離不一定產(chǎn)生美,還有GeoHash算法。

「附近的人」這樣的產(chǎn)品功能,你一定不陌生吧?

微信就有「附近的人」的功能,依托于位置信息,展示平臺(tái)上與你距離較近的用戶,這個(gè)功能在各種平臺(tái)上曾經(jīng)盛極一時(shí),依托「附近的人」的功能,也產(chǎn)生了一些灰色的產(chǎn)業(yè)鏈。

但今天要討論的不是如何利用「附近的人」來撩漢約P,而是站在產(chǎn)品的角度,分析「附近的人」是如何實(shí)現(xiàn)的。

如何實(shí)現(xiàn)?可能就是獲取了個(gè)人位置信息,將平臺(tái)上的所有用戶的位置信息按位置排序,然后逐一計(jì)算距離…

起初我也覺得這事就這么簡單。但果真如此,就不值得學(xué)習(xí)探討了。附近的人的實(shí)現(xiàn)策略,并不是一句話就能說清楚的。

首先,我們來回顧一些地理知識(shí)。

1、地球是圓的,分南北極,以地軸為中心自轉(zhuǎn)。

2、縱切線是經(jīng)線,常用「經(jīng)度」來衡量;橫切線是緯線,常用「緯度」來衡量;

3、緯線赤道往北極方向稱為「北緯」,往南極方向稱為「南緯」;經(jīng)線地軸往左方向是「西經(jīng)」,往右方向是「西經(jīng)」;經(jīng)線和緯線相交的點(diǎn)叫「坐標(biāo)」,如下圖中的紅點(diǎn):

也就是說,我們每個(gè)人目前所在的位置,都在某一條經(jīng)線和緯線的相交點(diǎn)上,都有一個(gè)「坐標(biāo)」,我們也常說「位置」。

那手機(jī)應(yīng)用是如何獲取我們的位置的呢(手機(jī)如何定位,知道我們?cè)谀睦铮?/p>

目前常用的定位技術(shù)有GPS定位、基站定位、WiFi輔助定位、AGPS定位、Glonass定位、北斗定位等。具體這些技術(shù)是什么原理這里不細(xì)講了,通過這些技術(shù),我們的位置會(huì)換算成一個(gè)「坐標(biāo)」,使用坐標(biāo)點(diǎn)(XX.XXXXX,Y.XXXXX)來描述,我們也常說這是「經(jīng)緯度」。

假如我們都獲取到了平臺(tái)上的用戶位置所在的坐標(biāo)點(diǎn),就可以計(jì)算你和TA的距離,就知道TA是不是你附近的人了。

如何計(jì)算你和TA的距離呢?

坐標(biāo)值保留小數(shù)5位,大概就可以精確到1米左右,比如A用戶和B用戶坐標(biāo)點(diǎn)A(20.38635,93.85210)與B(20.638635,93.85212)Y軸相差93.85212-93.85210 = 0.00002,相差在2米左右;

在緯度相等的情況下:

*經(jīng)度每隔0.00001度,距離相差約1米;

*每隔0.0001度,距離相差約10米;

*每隔0.001度,距離相差約100米;

… 以此類推

?*在經(jīng)度相等的情況下:

*緯度每隔0.00001度,距離相差約1.1米;

*每隔0.0001度,距離相差約11米;

*每隔0.001度,距離相差約111米;

… 以此類推

但并不是所有用戶都在同一條經(jīng)線或者緯線上直接算直線距離,如果用戶量較大的情況下,要這樣使用二維坐標(biāo)(x,y)來計(jì)算距離是不現(xiàn)實(shí)的,其次,真實(shí)記錄用戶所在的經(jīng)緯度,且在多個(gè)地方使用經(jīng)緯度來計(jì)算位置,有一定的隱私問題。

如果我們想要更快地得知你所在的位置附近,都有哪些人,必須尋找快一點(diǎn)的方式,比如數(shù)據(jù)庫在數(shù)據(jù)量較大且需要排序時(shí),會(huì)經(jīng)常用到索引來提高計(jì)算效率。

GeoHash算法將二維的經(jīng)緯度(x,y)轉(zhuǎn)換成一維信息(字符串),同時(shí)解決了隱私問題。

以下圖為例,把某個(gè)區(qū)域劃分為9個(gè)格子,9個(gè)給格子分別命名為WX4ER,WX4G2、WX4G3等這樣的字符串,每一個(gè)字符串是某個(gè)格子的代號(hào),用這個(gè)代號(hào)來代表被劃分的子區(qū)域。

也就是說,每個(gè)格子(子區(qū)域)內(nèi)所有的點(diǎn)(經(jīng)緯度坐標(biāo))都共享相同的GeoHash字符串,大家表示自己的所在位置時(shí),只需要說出該字符代號(hào)(比如我們?cè)谧鲎晕医榻B時(shí)說我是廣州天河人,“天河”就是廣州被劃分的其中一個(gè)格子),這樣既可以保護(hù)隱私(只表示大概區(qū)域位置而不是具體的點(diǎn)),一維的信息也比較容易計(jì)算和做緩存,只要格子劃分地越小,距離就越精確。

那GeoHash字符串如何表示自己的精確等級(jí)呢?

GeoHash字符串越長,表示的范圍越精確。如圖所示,5位的編碼能表示10平方千米范圍的矩形區(qū)域,而6位編碼能表示更精細(xì)的區(qū)域(約0.34平方千米)

GeoHash字符串相似的表示距離相近,比如上圖中的:

  • WX4G09和
  • WX4G08較近,和
  • WX4FBX較遠(yuǎn)

這樣可以利用字符串的前綴匹配來查詢附近的POI信息(POI信息表示一棟房子、一個(gè)商鋪、一個(gè)郵筒、一個(gè)公交站等),在地圖程序中找附近的醫(yī)院、加油站等都有應(yīng)用。

同樣地,我們可以用此方法來圈到同一區(qū)域(格子)或者附近區(qū)域的人群,再計(jì)算大概的距離,而不用把與所有人的距離計(jì)算出來,再做排序。

再來回顧一下兩種計(jì)算方法:

(1)只保存了每個(gè)人的坐標(biāo),要找出某個(gè)用戶附近的人

  • 把所有人的坐標(biāo)與當(dāng)前用戶的坐標(biāo)計(jì)算一次,算出距離
  • 按找算出的距離升序排列,返回附近的人

(2)保存了用戶的坐標(biāo)+GeoHash字符串,要找出附近的人

  • 按區(qū)域字符串相似度劃出該區(qū)域的人群,區(qū)域劃分越小,距離越近。

很明顯,2方法要快一些。

GeoHash字符串在位置接近矩形邊界時(shí)不太準(zhǔn)確。

比如紅色的點(diǎn)是A用戶,綠色的兩個(gè)點(diǎn)從上到下分別是B用戶和C用戶,但在圈定人群時(shí)會(huì)發(fā)現(xiàn)距離A較遠(yuǎn)的C用戶的GeoHash編碼與A一樣(因?yàn)樵谕粋€(gè)GeoHash區(qū)域塊上),而較近的B用戶的GeoHash編碼與A不一樣,算起來好像C與A較近。

  • A:WX4G0
  • B:WX4G2
  • C:WX4G0

所以,除了區(qū)域的劃分盡可能小來縮小邊界問題,在距離要求不是很精確時(shí),可以同時(shí)返回以A為中心區(qū)域的其他8個(gè)點(diǎn)附近的人。

Geohash的長度越長時(shí),表示距離越近(大部分時(shí)候準(zhǔn)確)。如上圖,6位的Geohash長度距離大概在2.4公里,8位的Geohash長度,大概在8米左右的距離誤差,9位的Geohash長度,大概就是2米了。

如此,產(chǎn)品在準(zhǔn)備類似附近的人這樣的產(chǎn)品需求時(shí),可以給到大概地理范圍內(nèi)的值,讓研發(fā)知道你所謂的「附近」,邊界在哪里。

 

作者:余秋楠

來源:微信公眾號(hào)【程序員和產(chǎn)品經(jīng)理】

本文由 @余秋楠 授權(quán)發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)作者許可,禁止轉(zhuǎn)載。

更多精彩內(nèi)容,請(qǐng)關(guān)注人人都是產(chǎn)品經(jīng)理微信公眾號(hào)或下載App
評(píng)論
評(píng)論請(qǐng)登錄
  1. mongodb數(shù)據(jù)庫自帶的方法,幾行代碼就能實(shí)現(xiàn)….不用這么復(fù)雜的

    來自四川 回復(fù)
  2. 據(jù)說微信是依靠移動(dòng)基站來計(jì)算的

    來自內(nèi)蒙古 回復(fù)
  3. 等維度間坐標(biāo)距離能這樣計(jì)算么?你說是在赤道吧,地球是圓的啊

    來自湖北 回復(fù)
    1. 是啊,赤道上1經(jīng)度的距離和北極圈上1經(jīng)度的距離是不同的

      回復(fù)
  4. 有理有據(jù)

    來自北京 回復(fù)
  5. 厲害了。。

    來自浙江 回復(fù)