Lucene 如何通过GeoHash 查询距离
2014-02-13 14:52
323 查看
之前用Lucene做过位置距离查询的项目,其中Lucene搜索定位距离的原理就是GeoHash,关于GeoHash的介绍看这里GeoHash 介绍,这篇文章要说的是如何根据GeoHash查询距离。
以下面以这幅图来看,图片将经度为0作为X轴的原点,纬度为0作为Y轴的原点,图中为了问题简单化,仅化了3层,实际中3层是不够的。
假设坐标轴正方向表示1,负方向表示0。那么按照GeoHash方法划分区域,则A到J的GeoHash分别为:
情况1:
我们看E、F两个点,其中前两层都是11,仅第三层不一致,E、F离得很近。
情况2:
我们看E、I两个点,第二、三层匹配,仅第一层不一致,E、I却离得很远。同理B、J也一样。
推测结果:
那么我们可以这样认为,GeoHash匹配距离时,必须从前往后,直到第一个不能匹配为止,匹配的层数越多越相近。
情况3:
拿着结果1,我们看F、G两个点,三层完全匹配,是不是F、G的距离要比E、F的距离近呢?不是,E、F距离更近。
情况4:
加速A、B、C、D无限靠近原点,那么A、B、C、D应该离得非常近,但是我们看GeoHash,A、B、C、D并不是按照从前往后匹配的。
分析结果
GeoHash并不是通过从前往后匹配来判断距离的,推测结果是错误的,那是通过什么呢?下面是我的猜测,具体实现思路还需要看看Lucene的源码。
A、B、C、D四个点,如果按字符串从前往后匹配,那么匹配程度非常低,但是如果把Hash当成一个二进制数,100表示4,而011表示3,通过数的差的绝对值,我们发现,无论是经度还是维度,A、B、C、D之间的差的绝对值都不会大于一。因为A、B、C、D无限靠近原点,即使有Geo划分有无限层,A的维度是1 0 0 0 0 0...(无限0),B的维度是0 1 1 1 1 1...(无限1),那么他们的绝对值仍然不会大于1。同样的,ABCD任意两点的经纬度差绝对值不会大于1。由于都是整数,除了0之外,最小差绝对值就是1。
由此我们可以推论:判断两个点的距离,是通过GeoHash的经纬度Hash分别按照二进制取差,绝对值越小,则距离越近。
至于经度和维度的合并的距离,由于经纬度是完全垂直的,就可以根据平方和(勾股定理)来定了。
如何判断F、G要比E、F远,应该就没有办法,因为这儿划分的层次太少,当划分层次多的时候,经纬度绝对值差E、F自然会比F、G小。所以,分层的大小直接影响到距离的精度。
以上都是自己分析的,不知是否正确,如有错误,欢迎批评指正。
以下面以这幅图来看,图片将经度为0作为X轴的原点,纬度为0作为Y轴的原点,图中为了问题简单化,仅化了3层,实际中3层是不够的。
假设坐标轴正方向表示1,负方向表示0。那么按照GeoHash方法划分区域,则A到J的GeoHash分别为:
位置点 | GeoHash经度值 | GeoHash纬度值 | GeoHash值(经度+维度) |
A | 1 0 0 | 1 0 0 | 11 00 00 |
B | 1 0 0 | 0 1 1 | 10 01 01 |
C | 0 1 1 | 0 1 1 | 00 11 11 |
D | 0 1 1 | 1 0 0 | 01 10 10 |
E | 1 1 0 | 1 1 0 | 11 11 00 |
F | 1 1 1 | 1 1 1 | 11 11 11 |
G | 1 1 1 | 1 1 1 | 11 11 11 |
H | 1 1 1 | 0 1 1 | 01 11 11 |
I | 0 1 0 | 0 1 0 | 00 11 00 |
J | 0 0 0 | 1 1 1 | 01 01 01 |
我们看E、F两个点,其中前两层都是11,仅第三层不一致,E、F离得很近。
情况2:
我们看E、I两个点,第二、三层匹配,仅第一层不一致,E、I却离得很远。同理B、J也一样。
推测结果:
那么我们可以这样认为,GeoHash匹配距离时,必须从前往后,直到第一个不能匹配为止,匹配的层数越多越相近。
情况3:
拿着结果1,我们看F、G两个点,三层完全匹配,是不是F、G的距离要比E、F的距离近呢?不是,E、F距离更近。
情况4:
加速A、B、C、D无限靠近原点,那么A、B、C、D应该离得非常近,但是我们看GeoHash,A、B、C、D并不是按照从前往后匹配的。
分析结果
GeoHash并不是通过从前往后匹配来判断距离的,推测结果是错误的,那是通过什么呢?下面是我的猜测,具体实现思路还需要看看Lucene的源码。
A、B、C、D四个点,如果按字符串从前往后匹配,那么匹配程度非常低,但是如果把Hash当成一个二进制数,100表示4,而011表示3,通过数的差的绝对值,我们发现,无论是经度还是维度,A、B、C、D之间的差的绝对值都不会大于一。因为A、B、C、D无限靠近原点,即使有Geo划分有无限层,A的维度是1 0 0 0 0 0...(无限0),B的维度是0 1 1 1 1 1...(无限1),那么他们的绝对值仍然不会大于1。同样的,ABCD任意两点的经纬度差绝对值不会大于1。由于都是整数,除了0之外,最小差绝对值就是1。
由此我们可以推论:判断两个点的距离,是通过GeoHash的经纬度Hash分别按照二进制取差,绝对值越小,则距离越近。
至于经度和维度的合并的距离,由于经纬度是完全垂直的,就可以根据平方和(勾股定理)来定了。
如何判断F、G要比E、F远,应该就没有办法,因为这儿划分的层次太少,当划分层次多的时候,经纬度绝对值差E、F自然会比F、G小。所以,分层的大小直接影响到距离的精度。
以上都是自己分析的,不知是否正确,如有错误,欢迎批评指正。
相关文章推荐
- lucene如何通过docId快速查找field字段以及最近距离等信息?
- lucene如何通过docId快速查找field字段以及最近距离等信息? - zhanlijun
- Flex中如何通过paddingTop样式,设置TabNavigator控件内容与Tabs间距离
- 如何通过 SQL Server 链接服务器和分布式查询使用 Excel
- android中如何通过WIFI的强度来计算每个Ap到手机的距离和手机的方向?
- 如何通过 SQL Server 链接服务器和分布式查询使用 Excel
- 如何通过SQL查询某个报表挂载的Responsibility
- 如何通过域名来查询dns服务商
- 【百度地图API】如何根据摩卡托坐标进行POI查询,和计算两点距离
- [No0000CB]如何在命令行(cmd)通过TCP/IP端口(port)查询所在的进程号(pid)或进程名称,并终止该进程
- LBS的球面距离计算及Geohash方案探讨(LBS之一)
- 如何通过破解hash来获取管理员密码(转)
- 如何通过 SQL Server 链接服务器和分布式查询使用 Excel
- 【连载】关系型数据库是如何工作的?(15) - 查询管理器之Hash Join
- lucene查询 之 TermQuery,通过项查询,及代码示例;TermQuery不使用分析器所以建议匹配不分词的Field域查询
- 【Maven+SSM】如何通过Mybatis写一个中文查询请求及所遇到的问题
- Geohash距离估算
- 【鉴别】日版iPhone如何通过IMEI查询运营商
- 装饰者模式的学习(c#) EF SaveChanges() 报错(转载) C# 四舍五入 保留两位小数(转载) DataGridView样式生成器使用说明 MSSQL如何将查询结果拼接成字符串 快递查询 C# 通过smtp直接发送邮件 C# 带参访问接口,WebClient方式 C# 发送手机短信 文件 日志 写入 与读取