有人说地球是个庞大的球体,那在地图上看也就是一堆红点。但你想在那些红点里抠出几厘米宽、几厘米高的定位代码?那得用 Geohash 这种“把地球切碎再重组”的刀法。想象一下,先把地球切成一亿片,每片都贴个编号(Bitwise),然后给这亿个编号丢进一个哈希函数里。哈希函数是个庞大的格网系统,每放多少号,就把它丢进对应的那个小方格,再切分、再哈希、再丢进下一个方格。
这就好比你在一个大箱子里扔硬币,硬币落在哪个面,你就知道它归于哪个区域。 拿到这一亿个坐标,再丢进 Geohash 算法。算法有个神技:滑动窗口。你不需求从最左边启动算,也不需求从最右边启动算。你只需求不停地往左滑、往右滑,与此同时不断往下一层切(细分)。左边滑到哪儿,就把这局部的特征丢进去;右边滑到哪儿,把右半边的特征丢进去。滑到哪一步,就生成多少位。滑两下,生成十六进制;滑四下,生成二进制。滑到最终一层十六进制,就拼成最终的字符串了。 这就解释了为啥 Geohash 像反直觉。地中海挺大,但四周全是海洋,中间一小块陆地。
要是你只用经纬度,地中海归红海那方,红海归黑海那方,地中海就被分成了两半。但用 Geohash?出于它的网格是等间距的,故此你不管地中海在哪边,只要形状够大,它自己就能塞进自己的块,就连能塞进大海里。它不在乎方向,只在乎“够不够大”。
这就是它不管经纬度,只管面积的缘由。 再举个具体的例子,比如我想找中国东北角的那块地方。你先定义一个网格面,从起点启动往东滑一格。
这一格里全是南方,没啥东西。再往东滑一格,还是南方。
这时候你发现,你滑过的这整个区域,实际上都指向“中国”这个方位。
这时候你就只需求用经纬度,把“中国”这个抽象概念,用具体的坐标点指出来。但要是你想要那最东边的中国边界点,你非得把网格细分到小数点后大量位才行,不然精度不够。
要是不用 Geohash,你直接拿经纬度,这一千万公里宽的网格面里,找不到一个专门负责“最东点”的格子,那就得先扔数字进去找,再把找到的数字扔回去找。Geohash 直接在第一步扔数字进去,就把这一刀的分割逻辑直接给切断了。 关于它的长度。大家常听到的 Geohash 一般是 8 位,也就是十六进制。但这只是数字的一局部,它实际上代表的是 32 位。就像你一段代码,代码里有常量、变量、循环,还有那些看不见的隐藏位。Geohash 的这 32 位,拍板了你能形成多少个不同的区域。
比如 32 位全是 0,就对应一个点;全是 1,就是一个彻底独立的块。
故此 8 位只是一个默认值,你想让精度更高,要么想生成更短的路径,彻底能够自己调整那些低位的值。
要是写成 16 位,那就是 16 进制字符串,每个字符 4 位。
比如“0123”,这个字符串本身就代表 32 位里的四舍五入效果。 还有几个细节务必懂。它有一个“最短距离”的概念。对于某些细小的区域,比如几百米宽,经纬度可能还是能把它切分出两个,但 Geohash 可能认定忒细节了,直接合并成一个。
这就害得同样的区域,经纬度是 A 和 B,Geohash 却是同一个。
这听起来矛盾不?实际上是出于它不在乎坐标的细小变化,只要面积够大,区域划分就稳当。就像你画地图,细一点还是细一点,但要是你确实要在地图上找个精确点,还是得看经纬度。Geohash 是拿来做“区域二分法”的,不是拿来做“坐标定位”的。它精通告诉你“这片土地归哪位管”,不精通告诉你“这块土地具体在哪一像素”。 还有一个冷知识:它生成的字符串长度实际上和输入区域的大小成正比。面积越大,生成的位数越多,字符串越长。面积越小,位数越少,字符串越短。
这就意味着,要是你想生成一个唯一的 ID,并且这个 ID 要尽可能短,务必保证你的区域充足大,大到能覆盖掉所有的噪声。
要是区域忒小,生成的字符串可能和某个别的路径重叠,那就白费了。
故此它不是通用的 ID 生成器,而是地理区域划分的专家。 最终说个应用点。在导航软件里,用经纬度计算距离忒慢,得用 Haversine 公式,那是个二维平面公式,对三维球体只看了一半。而 Geohash 能够算出两个区域之间的“距离”,这个距离在网格里是能够直接相减的。对于距离挺近的两个点,比如北京和天津,用经纬度算出来挺远,但在 Geohash 的网格里,它们可能连同一个区,就连同一个格子里。
这就解释了为啥在线地图拉个距离参考框(Radius),能强行把它们圈在一起,视觉上它们就“近”了。
这就是 Geohash 在移动端做“大区域定位”时的杀手锏。 好了,目前你能够试着在脑子里模拟一下这个过程了。先想一个大盒子,往盒子里扔千百万次硬币,看它们落在哪一层。再想下一层,要是一层满了,又往下一层切。
不管层数多少,只要把每一层每一格里的特征加起来,最终拼成一串数字,那就是最终的 Geohash。它就像是一个把地球强行塞进网格的强力胶水,别看有点粗暴,但在某种维度下,它确实能解决经纬度算不出来的谜题。