前言
- 以前在实现查找特定经纬度附近最近目标用户时遇到了一个问题,就是要查找出目标用户需要遍历数据库,进行经纬度的计算,然后进行排序,这种自然不是一种比较好的实现方式。例如,现在我们有一个平台,数据库记录着线下商家的全部经纬度,一个用户通过平台发送了当前位置的经纬度,需要分别查询出100m , 200m ,500m,1km ,10km等的商家,或者需要查询出附近最近的10个商家,如果采取这种做法,当商家的数量到达一定程度,就会出现查询特别慢的情况,这种情况下,推荐使用geohash。
介绍
- geohash时一种将二维的地理位置转换为一维进行查询的一种方式。例如geohash32,我们取出一张世界地图,将之等分为32块,每一块给予一个编码,那么在数据库记录的时候,我们只需要记住这一编码。当我们进行查询的时候,如果编码是相同的,我们就知道他们是通一块区域的地理位置。如下 :
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ef9184e200a01989d8f5066cef073447.png)
当然,我们还可以在每个小格子中再划分32个格子,无限递归。递归的越多,划分的格子越小,那么就目标位置的geohash就越长,那么精度就约高。例如 wx5jv4u6 就是北京某一处的geohash。(8位经度在后面介绍。)
详细请看这篇文章
https://www.jianshu.com/p/1ecf03293b9a
java实现
package com.koubei.collect_script.demo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author kelin.ll
* @date on 2018/6/13
*/
public class GeoHashDemo {
private LocationBean location;
/**
* 1 2500km;2 630km;3 78km;4 30km
* 5 2.4km; 6 610m; 7 76m; 8 19m
*/
private int hashLength = 8; //经纬度转化为geohash长度
private int latLength = 20; //纬度转化为二进制长度
private int lngLength = 20; //经度转化为二进制长度
private double minLat;//每格纬度的单位大小
private double minLng;//每个经度的倒下
private static final char[] CHARS = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
pub