Redis GeoHash 测距
GeoHash本质上是空间索引的一种方式,其基本原理是将地球理解为一个二维平面,将平面递归分解成更小的子块,每个子块在一定经纬度范围内拥有相同的编码。以GeoHash方式建立空间索引,可以提高对空间poi数据进行经纬度检索的效率。由于采用的是base32编码方式,即Geohash中的每一个字母或者数字都是由5bits组成(2^5 = 32,base32),这5bits可以有32中不同的组合(0~31),这样我们可以将整个地图区域分为32个区域,通过00000 ~ 11111来标识这32个区域。
Redis 3.2版本之后增加。
使用场景:存储地理位置、附近的人。
代码实现方法
定义实体类
/**
* 地方实体
*
* @author fengyn
* @since 2021/4/26 15:50
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Place {
/**
* 地名
*/
private String name;
/**
* 经度
*/
private Double longitude;
/**
* 经度
*/
private Double latitude;
复制代码
初始化数据
@PostConstruct
private void setGeo(){
addGeo(new Place("浙港国际",120.093312,30.309403));
addGeo(new Place("丰潭路地铁口",120.109624,30.281936));
addGeo(new Place("杭州东站",120.212998,30.291331));
addGeo(new Place("杭州汽车西站",120.09105,30.261022));
}
private void addGeo(Place place){
String geo = "geo";
redisTemplate.opsForGeo().add(geo,
new Point(place.getLongitude(),place.getLatitude()),place.getName());
}
复制代码
GeoHash实际上是存在zset里,score存geohash算法计算出来的值
计算两个位置的距离
Distance distance(K var1, M var2, M var3, Metric var4);
Diststance有两个属性:double value(距离) Metric metric(单位)
var1 表示redis key值
var2 var3 表示zset两个位置的key值
var4 表示距离单位(可不传,默认单位为米)
String geo = "geo";
Distance distance = redisTemplate.opsForGeo().distance(geo,"杭州东站", "杭州汽车西站", Metrics.KILOMETERS);
复制代码
结果
{
"value": 12.1894,
"metric": "KILOMETERS"
}
复制代码
以中心位置为圆心找出指定半径范围内的位置
GeoResults<GeoLocation> radius(K var1, Circle var2, GeoRadiusCommandArgs var3);
GeoLocation有两个属性 : T name (zset中key值) ,Point point (返回 经纬度 double x,double y);
GeoResults有两个属性 : Distance averageDistance(平均距离) ,List content (返回GeoLocation属性);
var1 表示redis key值
var2 表示圆心坐标位置
var3 表示添加过滤排序条件
includeDistance 包含距离
includeCoordinates 包含经纬度
sortAscending 正序排序
limit 限定返回的记录数
String geo = "geo";
GeoResults<RedisGeoCommands.GeoLocation<Object>> ret =
redisTemplate.opsForGeo().radius(geo, //丰潭路坐标
new Circle(new Point(120.109624,30.281936), new Distance(1, Metrics.KILOMETERS)),
RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
.includeDistance().limit(3).includeCoordinates().sortAscending()));
复制代码
结果
{
"averageDistance": {
"value": 2.1217666666666664, //平均距离
"metric": "KILOMETERS"
},
"content": [
{
"content": {
"name": "丰潭路地铁口",
"point": {
"x": 120.10962277650833,
"y": 30.281934749809132
}
},
"distance": {
"value": 2.0E-4,
"metric": "KILOMETERS"
}
},
{
"content": {
"name": "杭州汽车西站",
"point": {
"x": 120.09105116128922,
"y": 30.26102076552342
}
},
"distance": {
"value": 2.9317,
"metric": "KILOMETERS"
}
},
{
"content": {
"name": "浙港国际",
"point": {
"x": 120.09330958127975,
"y": 30.309403523012882
}
},
"distance": {
"value": 3.4334,
"metric": "KILOMETERS"
}
}
]
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END