Java-使用Redis GEO测算经纬度距离

一、Redis GEO相关命令操作

GEO也是Redis中提供的一种数据类型,可以将其理解成ZSet有序集合类型

1.1GEOADD

GEOADD cars -115.17087 36.12306 my-car


向GEO集合cars中添加一个键为my-car,值为-115.17087 36.12306。

第一个参数为GEO集合名称,第二个参数为经度,第三个参数为纬度,第四个参数为成员名称。

GEOADD cars -115.171971 36.120609 robins-car


再向同一个集合cars中添加一个robins-car坐标。

GEO与ZSET相同,多次添加相同的成员KEY,将会覆盖以前的内容,即不允许重复的成员KEY。

1.2GEODIST

GEODIST cars my-car robins-car


测算两个成员坐标的距离,即测算cars集合中,根据my-car与robins-car的经纬度计算两者相距的距离。默认返回的距离单位为米,比如"90.7082"米。

GEODIST cars my-car robins-car km


测算两个坐标的距离,返回值单位为km千米。

1.3GEORADIUS

GEORADIUS cars -115.17258 36.11996 100 m


刷选出集合cars中距离经纬度-115.17258 36.11996的100米范围内的成员名称数据。会返回成员键,即robins-car、my-car。

1.4GEORADIUSBYMEMBER

GEORADIUSBYMEMBER cars robins-car 100 m WITHDIST


刷选出集合内距离键robins-car 100米范围内的成员名称,并且一起返回距离该指定的键多少米。

1.5ZREM

ZREM cars my-car


移除集合中某个键,与ZSET有序集合使用的相同命令。

二:Spring中RedisTemplate操作。

2.1导入依赖

        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

2.2简单配置

  #redis相关配置
  redis:
  database: 1
  # 配置redis的主机地址,需要修改成自己的
  host: localhost
  port: 6379
  password: 123456
  timeout: 5000

2.3代码示例

有了Redis GEO相关命令后,我们便可以轻松地来计算两个经纬度之间的距离、筛选出距离某个经纬度100米范围内的数据了。

@Component
public class GeoUtil {
 
    @Autowired
    private RedisTemplate redisTemplate;
 
    private static final String GEO_KEY = "DISTANCE";
 
    /**
     * 将经纬度信息添加到redis中
     * @param certId 标识
     * @param longitude 经度
     * @param latitude 纬度
     */
    public void geoAdd(String certId, double longitude, double latitude) {
        GeoOperations geoOperations = redisTemplate.opsForGeo();
        Point point = new Point(longitude, latitude);
        RedisGeoCommands.GeoLocation geoLocation = new RedisGeoCommands.GeoLocation(certId, point);
        geoOperations.add(GEO_KEY, geoLocation);
    }
 
    /**
     * 两个人之间的距离
     * @param certId1
     * @param certId2
     * @return
     */
    public double distanceBetween(String certId1, String certId2) {
        GeoOperations geoOperations = redisTemplate.opsForGeo();
        Distance distance = geoOperations.distance(GEO_KEY, certId1, certId2);
        return distance.getValue();
    }
 
    /**
     * 查询距离某个人指定范围内的人,包括距离多少米
     * @param certId
     * @param distance
     * @return
     */
    public Map<String, Double> distanceInclude(String certId, double distance) {
        Map<String, Double> map = new LinkedHashMap<>();
 
        GeoOperations geoOperations = redisTemplate.opsForGeo();
        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = geoOperations.radius(GEO_KEY, certId, new Distance(distance), geoRadiusCommandArgs.includeDistance());
        if (geoResults != null) {
            Iterator<GeoResult<RedisGeoCommands.GeoLocation<String>>> iterator = geoResults.iterator();
            while (iterator.hasNext()) {
                GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult = iterator.next();
                // 与目标点相距的距离信息
                Distance geoResultDistance = geoResult.getDistance();
                // 该点的信息
                RedisGeoCommands.GeoLocation<String> geoResultContent = geoResult.getContent();
                map.put(geoResultContent.getName(), geoResultDistance.getValue());
            }
        }
        return map;
    }
 
 
}

GeoUtil geoUtil = springApplicationContext.getBean(GeoUtil.class);
geoUtil.geoAdd("北京西站", 116.328103,39.900835);
geoUtil.geoAdd("北京南站", 116.385488,39.87128);
geoUtil.geoAdd("北京西站-南广场", 116.327766,39.898944);
geoUtil.geoAdd("北京西站-南进站口", 116.327765,39.899347);
geoUtil.geoAdd("中铁设计大厦", 116.328628,39.896485);
geoUtil.geoAdd("瑞海大厦", 116.326661,39.903778);
 
// 计算北京南站与北京西站之间的距离
double distance = geoUtil.distanceBetween("北京西站", "北京南站");
// 5898.4001
System.out.println(distance);
 
 
// 查询距离北京西站5000米范围内的地方
Map<String, Double> distanceInclude = geoUtil.distanceInclude("北京西站", 5000);
System.out.println(distanceInclude);

从百度地图看北京西站与北京南站的距离为5.9公里,即5900米,与计算出的5898.4001相差无几。

 


————————————————
原文链接:https://blog.csdn.net/weixin_50518271/article/details/122717870

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值