Geohash 是 Gustavo Niemeyer 在 2008 年发明的一个地理编码系统(geocode system),它将经度和纬度这个二维的地理坐标编码成一个由数字和字母组成的字符串。虽然 geohash 是从经纬度计算出来的,但是 geohash 并不能像经纬度那样能够表示出某个点在地图上的确切位置。实际上,Geohash 表示的是一个区域,这个区域内所有的点都有着相同的 geohash 值。这意味着,geohash 可以帮助用户隐藏确切的位置信息,从而更好地保护用户的隐私。虽然我们可以通过 geohash 得知用户所在的区域,但是我们却无法知道用户到底在这个区域中的哪个点。
很多基于位置的个性化服务都是基于 geohash 实现的。比如查找附近的人,寻找附近的餐厅等等。以查找附近的人为例,如果两个人所处位置的 geohash 相同,那么我们可以认为这两个人在空间上是相近的。至于具体有多近,这取决于 geohash 所表示的位置精度。通过改变 geohash 的长度,我们可以表示任意精度的位置:geohash 越短,其表示的区域越大,位置精度越低;相反,geohash 越长,其表示的区域越小,位置精度越高。
以天府广场(latitude: 30.6599157, longitude: 104.0638546)为例,下图展示了通过不断增加 geohash 长度提高展示位置精度的过程:
- 当 geohash 长度为 1 时,选择
w
- 当 geohash 长度为 2 时,选择
wm
- 当 geohash 长度为 3 时,选择
wm6
- 当 geohash 长度为 4 时,选择
wm6n
- 当 geohash 长度为 5 时,选择
wm6nj
- 当 geohash 长度为 6 时,选择
wm6nj2
需要注意的是,同一个地点在不同地图下的经纬度可能是不一样的。本文采用的是 OpenStreeMap。
经度与纬度
经纬度是由地球表面经线和纬线相交组成的一个坐标系统。每根经线和纬线都有不同的度数,叫经度和纬度。
地球是一个球体,经线连接南北两极,是半圆弧状。经过英国首都伦敦格林尼治天文台原址的那一条经线被定为 0° 经线,又叫本初子午线。本初子午线往东为东半球,往西为西半球。东西两个半球的经度范围均在 0° 至 180° 之间,合计360度。一般将西半球的经度范围记为 [-180°, 0°)
,而将东半球的为 (0°, 180°]
。
纬线与经线垂直的圆圈,任意两根纬线互相平行。赤道(实际上是地球表面的点随着地球自转产生的轨迹中最长的圆周线)是最大的纬线圈,纬度为 0°。赤道将地球分为南北两个半球,南北两个半球的纬度范围都是 90°,合计 180°。从赤道出发,向两极靠近,纬度越来越大,纬线圈越来越小。一般将南半球的纬度范围记为 [-90°, 0°)
,而将北半球的纬度记为 (0°, 90°]
。
南极点的纬度记为 90°S(或 -90°),北极点的纬度记为 90°N(或 +90°)。
算法原理
Geohash 是一种将二维的经纬度编码成一个字符串的地理编码方法,核心思想是区间二分:将地球编码看成一个二维平面,然后将这个平面递归均分为更小的子块。
当我们对一个地理坐标进行 geohash 编码时,先分别计算出经度和纬度各自的二进制编码,然后按照“从第 0 位开始,偶数位放经度,奇数位放纬度”的规则将