案例来源:@阿里技术
案例地址:https://mp.weixin.qq.com/s/vwhetMpQllczILptBNcoWg
0. 背景:闲鱼每天都有海量商品位置(点数据)与大量商圈(面数据)的匹配问题,如果计算每个点落在哪个面里,需要的计算复杂度非常高
1. 目标:在尽可能保持精度的前提下,快速判断每个商品位置(点数据)属于哪个商圈(面数据)
2. 方法:
1)使用GeoHash将地理位置数据编码为字符串数据
a. 将地理位置的经纬度,根据二分法转换成二进制串。如“30.01”,在[-90, 90]区间内为右边,第一位编码为“1”;在(0, 90]区间内为左边,第二位编码为“2”,依次类推得到二进制串编码
b. 按照“偶数位放经度,奇数位放纬度”的规则,将经纬度的二进制编码穿插,得到最终的二进制串,如“11100 11001 10011 10010 00111 00010”
c. 将二进制串转换为32进制数,如上面的二进制串编码为“wtmk72”
2)面数据GeoHash实现
a. 找到面数据外接矩阵
b. 计算外接矩阵左下角的GeoHash块
c. 逐步扫描整个外接矩阵
d. 扫描完成后删除与面数据完全不相交的GeoHash块
3)求临近GeoHash块的快速方法:观察GeoHash编码表的规律,结合GeoHash编码使用的Z阶曲线的特性,验证了一种通过查表来快速求相邻GeoHash字符串的方法
4)点数据与面数据的匹配:
a. 计算点数据的GeoHash
b. 计算面数据所包含的GeoHash
c. 如果点数据GeoHash属于面数据所包含的GeoHash,则准确匹配(如点数据“wtmk70r”,面数据也包含“wtmk70r”)
d. 如果点数据GeoHash属于面数据所包含的GeoHash块中部分包含的部分(如图中的2),则进一步用几何学计算方法确定(如射线法,从点发射一条射线与几何图形相交,如果相交的点是偶数,那么在图形外;是奇数,在图形内)
3. 使用效果:在闲鱼的实际应用中,10亿商品和1万商圈数据,使用本文的快速算法,只需要 10亿次GeoHash点编码 + 1万次GeoHash面编码 + 500万次“点是否在面内部”几何学运算,粗略换算为基本运算需要的次数约为1800亿次,运算量远小于传统方法的2亿亿次基本运算
4. 其它使用场景:用来快速处理点—点关系、面—面关系、点—线关系、线—线关系等问题
1)海量公交站台与道路的从属关系
2)多条道路或铁路是否存在交点
——————
思考
1. 经纬度是两个维度对空间进行划分。如果现在计算一个新用户隶属于哪个群体,对特征空间也采用类似于GeoHash的编码方式,就能快速处理 海量用户与大量群体的从属关系
——————