使用 Redis GEO 获取两个坐标的直线距离、以及给定坐标获取半径不超过指定距离的元素

目录

    • 一、前言
    • 二、Redis GEO 常用命令介绍
    • 三、Redis GEO 获取两个坐标的直线距离
    • 四、Redis GEO 给定坐标获取半径不超过指定距离的元素

一、前言

      在做快递外卖等配送业务时经常需要使用到,计算配送员距离商家的直线距离,和检索商家坐标给定一个半径内全部的配送员,要想实现这两个功能可以直接使用Redis GEO进行坐标计算,这里会使用Redis命令演示和Java代码演示,Java代码会使用Spring Boot环境RedisTemplate操作Redis。

  • 需要集成文章可以查看:
    SpringBoot集成Lettuce客户端操作Redis:https://blog.csdn.net/weixin_44606481/article/details/133907103

  • 准备SpringBoot测试类,下面Java代码演示统一使用:

    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    public class RedisGeoTest {
    
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
    }
    

二、Redis GEO 常用命令介绍

# 添加坐标信息 可以一次性添加多个,member:城市名称
geoadd <key> <longitude> <latitude> <member> ...

# 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),可以一次性指定多个member
geopos <key> <member> ...

# 用于返回两个给定位置之间的直线距离距离单位可选m|km|ft|mi,withdist:加上可以返回间隔距离
geodist <key> <member1> <member2> m|km|ft|mi withdist

# 根据给定的经纬度,返回半径不超过指定距离的元素 距离单位可选m|km|ft|mi
georadius <key> <longitude> <latitude> <radius> m|km|ft|mi

# 根据给定元素的经纬度,返回半径不超过指定距离的元素
georadiusbymember <key> <member> <radius> m|km|ft|mi

# 用于获取一个或多个位置元素的 geohash 值,可以一次性获取多个
geohash <key> <member> ...

三、Redis GEO 获取两个坐标的直线距离

  • Redis命令演示
127.0.0.1:6379> geoadd geo_01 114.057939 22.543527 shenzhen
(integer) 1
127.0.0.1:6379> geoadd geo_01 114.171203 22.277468 xianggang
(integer) 1
127.0.0.1:6379> geodist geo_01 shenzhen xianggang km
"31.8021"
  • Java代码演示
    @Test
    public void t1() {
        String redisKey = "geo_01";
        redisTemplate.delete(redisKey);
        // 设置深圳市政府的坐标
        redisTemplate.opsForGeo().add(redisKey,new Point(114.057939,22.543527),"shenzhen");
        // 设置香港的坐标
        redisTemplate.opsForGeo().add(redisKey,new Point(114.171203,22.277468),"xianggang");
        // 获取两个城市之间的距离
        Distance distance = redisTemplate.opsForGeo().distance(redisKey, "shenzhen", "xianggang", RedisGeoCommands.DistanceUnit.KILOMETERS);
        System.out.println("获取两个城市之间的距离:"+distance.getValue()+" 千米");
        // 输出结果:获取两个城市之间的距离:31.8021 千米
    }

四、Redis GEO 给定坐标获取半径不超过指定距离的元素

  • Redis命令演示
127.0.0.1:6379> geoadd geo_02 114.057939 22.543527 shenzhen
(integer) 1
127.0.0.1:6379> geoadd geo_02 113.751884 23.021016 donguan
(integer) 1
127.0.0.1:6379> geoadd geo_02 114.415587 23.112368 huizhou
(integer) 1
127.0.0.1:6379> geoadd geo_02 114.171203 22.277468 xianggang
(integer) 1
127.0.0.1:6379> georadius geo_02 113.264499 23.130061 100 km
1) "donguan"
127.0.0.1:6379> georadius geo_02 113.264499 23.130061 110 km withdist
1) 1) "donguan"
   2) "51.3264"
2) 1) "shenzhen"
   2) "104.2642"
  • Java代码演示
    @Test
    public void t2() {
        String redisKey = "geo_02";
        redisTemplate.delete(redisKey);
        // 设置深圳市政府的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(114.057939, 22.543527), "shenzhen");
        // 设置东莞市政府的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.751884, 23.021016), "donguan");
        // 设置惠州市政府的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(114.415587, 23.112368), "huizhou");
        // 设置香港的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(114.171203, 22.277468), "xianggang");

        // 以广州市政府经纬度为中心,获取半径不超过最大距离的所有元素
        Point point = new Point(113.264499,23.130061);
        // 半径为110km
        Distance distance = new Distance(110, RedisGeoCommands.DistanceUnit.KILOMETERS);
        Circle circle = new Circle(point, distance);
        // 构造 GeoRadiusCommandArgs 对象
        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance()  // 设置为 true,表示返回距离信息
                .sortAscending();   // 设置为 true,表示按距离升序排列
        GeoResults<RedisGeoCommands.GeoLocation<Object>> radius = redisTemplate.opsForGeo().radius(redisKey, circle,geoRadiusArgs);
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content= radius.getContent();
        for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult:content){
            RedisGeoCommands.GeoLocation<Object> geoResultContent = geoResult.getContent();
            System.out.println("广州市政府110KM半径范围内城市:"+geoResultContent.getName() + " 相隔:" +geoResult.getDistance().getValue()+ " 千米");
        }
        // 输出结果:
        // 广州市政府110KM半径范围内城市:donguan 相隔:51.3264 千米
        // 广州市政府110KM半径范围内城市:shenzhen 相隔:104.2642 千米
    }

你可能感兴趣的:(java,redis,redis,缓存,java,spring)