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

news/2024/7/8 2:17:46 标签: redis, 缓存, java, spring

目录

    • 一、前言
    • 二、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代码演示统一使用:

    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代码演示
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代码演示
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 千米
    }

http://www.niftyadmin.cn/n/5189828.html

相关文章

flink的window和windowAll的区别

背景 在flink的窗口函数运用中&#xff0c;window和windowAll方法总是会引起混淆&#xff0c;特别是结合上GlobalWindow的组合时&#xff0c;更是如此&#xff0c;本文就来梳理下他们的区别和常见用法 window和windowAll的区别 window是KeyStream数据流的方法&#xff0c;其…

.nc格式文件的显示及特殊裁剪方式

最近我们遇到一个nc格式的文件&#xff0c;需要将它做成报告插图&#xff0c;bing搜索一番以后&#xff0c;了解到nc的全名为NetCDF(network Common Data Form)&#xff0c;是一种网络通用数据格式&#xff0c;广泛用于大气科学、水文、海洋学、环境模拟、地球物理等诸多领域。…

什么是JPA? JPA在springBoot中怎么使用

JPA&#xff08;Java Persistence API&#xff09;是Java EE 5规范中的一套ORM规范&#xff0c;用于在Java应用程序中进行对象关系映射&#xff08;ORM&#xff09;。它定义了一组标准API&#xff08;接口和类&#xff09;&#xff0c;用于在Java应用程序中管理持久化对象。 在…

06-流媒体-YUV数据在SDL控件显示

整体方案&#xff1a; 采集端&#xff1a;摄像头采集&#xff08;YUV&#xff09;->编码&#xff08;YUV转H264&#xff09;->写封装&#xff08;&#xff28;264转FLV&#xff09;->RTMP推流 客户端&#xff1a;RTMP拉流->解封装&#xff08;FLV转H264&#xff09…

LabVIEW编程开发NI-USRP

LabVIEW编程开发NI-USRP 可编程性是SDR的关键特性&#xff0c;它使人们能够将无线电外围设备转换为先进的无线系统。USRP是市场上最开放、最通用的SDR&#xff0c;可帮助工程师在主机和FPGA上使用各种软件开发工具构建系统。 有多种选项可用于对基于SDR的系统的主机进行编程。…

P2341 [USACO03FALL / HAOI2006] 受欢迎的牛 G

模板记录 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define endl "\n" #define x first #define y second #define int long long using namespace std; typedef long long ll; typedef pair<int, int> …

组合式API_侦听器

选项式API_侦听器 <template><h3>选项式API</h3><p>{{ count }}</p><button click"addCountHandle">增加</button> </template> <script> export default {data(){return{count:0}},methods:{addCountHandle…

FreeRTos延时函数xTaskDelayUntil的工作原理

通过一个简单的例子来解释 xTaskDelayUntil 的工作原理&#xff1a; 假设你有一个任务&#xff0c;需要每隔 100 个时钟节拍唤醒一次来执行某些操作。 初始化 pxPreviousWakeTime&#xff1a; 在任务开始时&#xff0c;你首先获取当前的时钟节拍数并将其赋值给 pxPreviousWa…