后续文章参见
地理空间索引:线段与多边形的GeoHash编码
地理空间索引:线段的GeoHash编码优化

1. 基于空间位置的服务

基于位置的服务型电商席卷而来,搭乘网约车去到目的地、搜索附近的餐馆酒旅,无不让人们感觉到便捷。比如打开滴滴APP,我们看到附近的车辆如下

那么问题来了,滴滴是怎么快速的匹配出乘客附近2公里的车辆的呢?

先讲最暴力的解法:首先获取乘客的经纬度坐标,然后和当前所有车辆的经纬度坐标计算距离,最后筛选留下距离小于两公里的车辆。这种解法计算量随着车辆规模线性增长,因此非常耗时。一种优化思路是按照经纬度坐标范围粗略筛选掉距离过远的车辆,然后在剩余的车辆里继续计算距离来进行精确筛选,但这同样需要遍历所有的车辆,仍然无法避免大量的时间开销。有没有不用遍历的解法?

上面的思考容易让我们联想到哈希散列的思路:遍历列表查找时间复杂度高,而创建哈希值散列后查找效率可以获得极大提升。尽管我们要考虑的场景是二维的,但是我们可以将经度和纬度分开来处理,也就是先后在经度和纬度上对空间进行编码,相当于在地球上打上网格,并且该网格具有层次(见下图),层次由高到低,代表的空间范围由大到小,描述的地理位置由粗到细;为了查找一个经纬度所在的网格,只需要按照网格层次由高到低进行匹配就可以了。

回到之前的问题,为了匹配乘客附近2公里的车辆,我们事先给乘客和所有车辆的经纬度坐标打上网格(期望网格恰巧就是2公里,实际不能保证这么精确),然后查找和乘客所在的网格相同的车辆即可。由于网格具有层次,于是这里的查找就可以避免遍历,而采取B树等一系列高效的算法进行实现了。

不知不觉中,我们已经在使用了GeoHash的思想开始解决问题了。

2. GeoHash基本原理

下面来正式介绍GeoHash算法。

GeoHash是一种通用的地理编码算法,是由Gustavo Niemeyer发明的,简言之,它可以将地理经纬度坐标编码为由字母和数字所构成的短字符串。它具有如下特性:

  1. 层级空间数据结构,将地理位置用矩形网格划分,同一网格内地理编码相同;
  2. 可以表示任意精度的地理位置坐标,只要编码长度足够长;
  3. 编码前缀匹配的越长,地理位置越邻近。

例如下图对北京中关村软件园附近进行6位的GeoHash编码结果,9个网格相互邻近且具有相同的前缀wx4ey。

那么GeoHash算法是怎么对经纬度坐标进行编码的呢?总的来说,它采用的是二分法不断缩小经度和纬度的区间来进行二进制编码,最后将经纬度分别产生的编码奇偶位交叉合并,再用字母数字表示。举例来说,对于一个坐标116.29513,40.04920的经度执行算法:

  1. 将地球经度区间[-180,180]二分为[-180,0]和[0,180],116.29513在右区间,记1;
  2. 将[0,180]二分为[0,90]和[90,180],116.29513在右区间,记1;
  3. 将[90,180]二分为[90,135]和[135,180],116.29513在左区间,记0;
  4. 递归上述过程(左区间记0,右区间记1)直到所需要的精度,得到一串二进制编码11010 01010 11001

同理将地球纬度区间[-90,90]根据纬度40.04920进行递归二分得到二进制编码10111 00011 11010,接着生成新的二进制数,它的偶数位放经度,奇数位放纬度,得到11100 11101 00100 01101 11110 00110,最后使用32个数字和字母(字母去掉a、i、l、o这4个)进行32进制编码,即先将二进制数每5位转化为十进制28 29 4 13 30 6,然后对应着编码表进行映射得到wy4ey6

对这样的GeoHash编码大小排序后,是按照Z形曲线来填充空间的,后来又衍生出多种填充曲线且具有多种特性,由于没有Z形曲线简单通用,这里就不赘述了。下表是GeoHash的编码长度与网格大小以及距离精度的关系,对于我们第一节讨论的匹配附近2公里的车辆,使用编码长度为5就可以了,如果需要更精细的匹配,可以在GeoHash匹配的结果上进行进一步的距离筛选。

3. 代码实现

目前比较高效实现的代码参考python-geohash,它支持Python和C两种语言环境,其设计思路主要是用移位操作来代替二分区间,实现效率非常高。其Python代码主要接口如下:

encode(latitude, longitude, precision=12)  # 编码
decode(hashcode, delta=False)  # 解码
bbox(hashcode)  # 边界经纬度
neighbors(hashcode)  # 8个近邻编码
expand(hashcode)  # 拓展编码

4. GeoHash的应用与注意事项

GeoHash的主要价值在于将二维的经纬度坐标信息编码到了一维的字符串中,在做地理位置索引时只需要匹配字符串即可,便于缓存、信息压缩。在使用大数据工具(例如Spark)进行数据挖掘聚类时,GeoHash显得更加便捷和高效。

但是使用GeoHash还有一些注意事项:

  1. 由于GeoHash使用Z形曲线来顺序填充空间的,而Z形曲线在拐角处会有突变,这表现在有些相邻的网格的编码前缀比其他网格相差较多,因此利用前缀匹配可以找到一部分邻近的区域,但同时也会漏掉一些。
  2. 一个网格内部所有点会共用一个GeoHash值,在网格的边缘点会匹配到可能较远但是GeoHash值相同的点,而本来距离较近的点却没有匹配到。这种问题可以这样解决:适当增加GeoHash编码长度,并使用周围的8个近邻编码来参与,因为往往只使用一个GeoHash编码可能会有严重风险!

地理空间索引:GeoHash原理相关推荐

  1. 地理空间索引:线段与多边形的GeoHash编码

    geohash简介文章参见 地理空间索引:GeoHash原理 优化线段的编码效率参见 地理空间索引:线段的GeoHash编码优化 在上一篇博客地理空间索引:GeoHash原理中,我们讨论了如何将一个经 ...

  2. geohash之2d 地理空间索引

    个人博客:https://suveng.github.io/blog/​​​​​​​ 2d 地理空间索引 概述 2D地理空间索引可以将文档与二维空间中的位置(例如地图上的点)相关联.MongoDB将位 ...

  3. 空间索引 - GeoHash算法及其实现优化

    转自原文 空间索引 - GeoHash算法及其实现优化 上篇博客中提到了空间索引的用途和多种数据库对空间索引的支持情况,那么在应用层以下,好学的小伙伴应该会考虑空间索引的实现原理了. 目前空间索引的实 ...

  4. geohash网格图_空间索引 - GeoHash算法及其实现优化

    前言 上篇博客中提到了空间索引的用途和多种数据库对空间索引的支持情况,那么在应用层以下,好学的小伙伴应该会考虑空间索引的实现原理了. 目前空间索引的实现有 R树和其变种GIST树.四叉树.网格索引等. ...

  5. Mongodb地理空间索引

    1.索引: 建立索引既耗时也费力,还需要消耗很多资源.使用{"bakckground":true}选项可以使这个过程在后台完成,同时正常处理请求.如果不包括background 这 ...

  6. MongoDB-JAVA-Driver 3.2版本常用代码全整理(4) - 地理空间索引

    MongoDB的3.x版本Java驱动相对2.x做了全新的设计,类库和使用方法上有很大区别.例如用Document替换BasicDBObject.通过Builders类构建Bson替代直接输入$命令等 ...

  7. MongoDB——索引类型之地理空间索引(Geospatial Index)

    目录 一.MongoDB官网地址 二.地理空间索引(Geospatial Index) 2.1.地理空间索引(Geospatial Index)的概述 2.2.地理空间索引(Geospatial In ...

  8. mongodb地理空间索引原理阅读摘要

    http://www.cnblogs.com/taoweiji/p/3710495.html 具体原理在上面 简单概述,(x,y)经纬度坐标,通过geohash的方式,通过N次方块四分割生成一个坐标码 ...

  9. 地理空间索引实现:z 曲线、希尔伯特曲线、四叉树, 最邻近几何特征查询、范围查询

    我的GIS/CS学习笔记:https://github.com/yunwei37/ZJU-CS-GIS-ClassNotes <一个浙江大学本科生的计算机.地理信息科学知识库 > 详细代码 ...

最新文章

  1. 为什么数据科学不值得?
  2. wpf richtextbox 存储到数据库并显示
  3. 【网络安全】一次实战中对tp5网站getshell方式的测试
  4. leetcode面试题 10.03. 搜索旋转数组(二分法)
  5. Flutter 底部向上动画弹出的菜单选项
  6. 【Kafka】kafka 客户端 控制台 flink 都无法消费的情况
  7. 蓝桥杯 ADV-21 算法提高 多项式输出
  8. 用VAE(variational autoencoder)做sentence embedding/representation或者其他任何结构数据的热presentation...
  9. 剖析360为什么要做路由器
  10. FeiQ(飞秋)更新用户列表的原理
  11. 对硬盘进行分区时,GPT和MBR有什么区别
  12. 模式识别和计算机科学与技术,模式识别与智能系统
  13. REUSE_ALV_GRID_DISPLAY_LVC-可编辑单元格
  14. Thinkphp5 引入第三方类库
  15. 豆瓣爬虫(从剧名获取ID)
  16. 最新研究动向:智能制造中可应用的技术【区块链与数字孪生】
  17. Appium: Windows系统桌面应用自动化测试(二)
  18. 今天给同学写5个数据结构算法的题...感觉很有价值的几个题..感兴趣的坐下。。
  19. 工具栏的打印图标不见了_显示屏下方的工具栏里的小图标不见了怎么弄回来
  20. 关于多台三菱PLC数据采集到SQL数据库,对接MES平台

热门文章

  1. TIM登陆时提示00001(TIM00001)
  2. WMS仓库管理系统---(13)订单管理--创建订单
  3. 浅谈 Mockito:Java 单元测试神器
  4. C语言程序设计算法题 -- lab09(1036 - 1039) 二分查找 itob 进制转换 Expands shorthand notations
  5. 时尚巨头确认遭遇勒索攻击、1100万部手机已感染木马|1月19日全球网络安全热点
  6. caioj1212:【计算几何】判断线段相交(快速排斥判断与跨立实验)
  7. Dijkstra算法模板
  8. 用c++求解一道简单的数学题
  9. 计算机科学精彩帖子收集--JAVA和分布式专栏
  10. XMLHttpRequest介绍