原理
通过将地球看成一个二维的平面图 ,然后将平面递归切分 成更小的模块,然后将空间经纬度数据进行编码生成一个二进制 的字符串,再通过base32将其转换为一个字符串 。最终是通过比较geohash的值的相似程度查询附近目标元素。
经纬度转geohash过程
- 经度/纬度 ------将实际的经度/纬度在整个空间范围内(-180~+180/-90~+90)不断二分 ------》经度/维度的二进制表示(位数越多越精确,即二分的次数越多越精确)
示例:北纬23.117596;纬度范围:-90°~+90°
在[-90, 0] [0, 90]中的右边:第一位1
在[0,45] [45, 90]中的左边:第二位0
在[0,22.5] [22.5,45]中的右边:第三位1
在[22.5,33.75] [33.75, 45]中的左边:第四位0
在[22.5,28.125] [28.125, 33.75]中的左边:第五位0
以此类推,最终得到纬度对应的二进制1,0,1,0,0,0,0,0,1,1;
按照类似的方式,可以得到东经113.326059;对应的二进制编码是1,1,0,1,0,0,0,0,1,0(经度的范围是-180°~+180°)
- 将经度和纬度的二进制表示进行组合编码 ,即 二进制 -》base32编码
- 将经纬度对应的二进制进行组合 ,偶数位放经度,奇数位放纬度,得到一个新的二进制序列
- 示例中的经纬度组合后得到:1,1,1,0,0 1,1,0,0,0 0,0,0,0,0 0,1,1,0,1
- 对新的二进制序列进行base32编码
- base32算法:用0-9、b-z(去掉a, i, l, o)这32个字符进行base32编码;
- 码表↓
- 将经纬度对应的二进制进行组合 ,偶数位放经度,奇数位放纬度,得到一个新的二进制序列

- 因为是32个字符,所以一次最多可以对5个bit位进行编码(2^5 => 32),所以要确保新序列的bit位数必须是5的倍数!(如下图)

- 通过上述方式就可以得到经纬度对应的geohash值
- 不同长度的geohash,对应的矩形区域大小,以长度6为例
precision = 6
total_bits = 6 * 5 = 30 bits
# 经纬度 bits 分配(交替编码)
# 位数代表了二分的次数,2^15就是格子的数量
lon_bits = ceil(30/2) = 15 bits # 经度
lat_bits = floor(30/2) = 15 bits # 纬度
# 格子数量
lon_grids = 2^15 = 32,768 个格子
lat_grids = 2^15 = 32,768 个格子
# 每个格子的度数大小
lon_grid_size = 360° / 32,768 = 0.010986°
lat_grid_size = 180° / 32,768 = 0.005493°
# 转换为公里
lon_grid_km = 0.010986° × 111.32 km/° = 1.223 km
lat_grid_km = 0.005493° × 110.54 km/° = 0.607 km