RedisGeo结合高德地图


前言

账号开篇之作,记录一下自己实现自己的项目的时候运用的一些功能

如果有错误的地方,欢迎评论区指正👏🏻


一、高德地图基本的一些API

这个在这里不列举了,前端会用到,而且开发者文档写得十分详细了,读者可以直接点链接去看看🔗

JavaScriptAPI-高德地图


二、使用RedisGeo的原因

本项目设计的思路为:调用百度地图的API,实时获得用户当前的定位(longitude和latitude),然后作为参数调用后端提供的接口,返回当前位置周围指定范围大小(半径大小)内的所有目标对象。


三、RedisGeo的基本使用方法

注意:以下所有的代码里面都是使用StringRedisTemplate

考虑到操作地图相关的数据里面包含比较多的数据类型,为了提高开发的效率,统一字符串形式来存储

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
  1. 添加位置成员,返回当前集合里面的成员数量(Long类型)
    public Long geoAdd(String key, double lon, double lat, String member){
        return stringRedisTemplate.opsForGeo().add(key, new Point(lon, lat), member);
    }   // 添加位置成员
     这里面的Point对应一个含经纬度数据的对象(需要说明的是在Redis里面key对应的是集合的名字,member对应的是集合里面的成员的名字,与成员一一对应的是其Score)


    大家可能会注意到里面的score的值是比较奇怪的值,其实是Redis使用特定算法把经纬度信息转换位一个64位的整数,以此保证地理位置的全球性和唯一性
  2. 提供key和member返回一个包含经纬度信息的Point对象
        public List<Point> geoPos(String key, String... members){
            return stringRedisTemplate.opsForGeo().position(key, members);
        }   // 获得不限数量成员经纬度

    这个方法可以传入多个member组成的集合members,返回的是一个经纬度对象列表

  3. 返回两个地点之间的距离(可以指定距离单位)
        public Distance geoDist(String key, String member1, String member2, Metrics metric){
            return stringRedisTemplate.opsForGeo().distance(key, member1, member2, metric);
        }

    metric形如Metric.KILOMETERS、Metric.METERS

  4. 返回指定成员附近所有的成员对象,返回的类型为:
    List<RedisGeoCommands.GeoLocation<String>>
        public List<RedisGeoCommands.GeoLocation<String>> geoRadiusByMember(String key,double lon, double lat,Double minDistanceKm, Double maxDistanceKm, Metrics metric, RedisGeoCommands.GeoRadiusCommandArgs args){
            return stringRedisTemplate.opsForGeo().radius(key, new Circle(new Point(lon,lat),new Distance(maxDistanceKm, metric)), args).getContent().stream()
                    .filter(result->result.getDistance().getValue()>=minDistanceKm)
                    .map(GeoResult::getContent)
                    .collect(Collectors.toList());
        }

    这个方法实际调用的是

    GeoResults<RedisGeoCommands.GeoLocation<M>> radius(K key, Circle within, RedisGeoCommands.GeoRadiusCommandArgs args);

    这里面的Circle对象包含经纬度信息和圆周半径

  5. 当然还有一个很重要的参数args,这个参数可以对返回的结果进行各种各样的设置,解释一下这个参数的具体值的含义:

  6. RedisGeoCommands.GeoRadiusCommandArgs
            .newGeoRadiusArgs()
            .includeCoordinates()	// 包含坐标信息
            .includeDistance()		// 包含距离信息
            .limit(9)				// 限制返回数量
            .sortAscending()		// 按照距离排序

        这里我设置了filter来实现一个同心圆的范围,在实际应用中可以排除过于接近的对象


四、实际应用例子

目标:调用百度地图获得当前位置经纬度信息,并且作为参数调用接口返回附近(用半径自行定义附近)的所有目标地点,从而实现为用户提供周围指定营业点的地图位置和导航路线

(营业点位置信息由后台管理系统添加,本人测试的时候采用爬虫爬取足量地点数据,以CSV文件导入Redis内)

    public void syncLogisticsLocationData(MultipartFile file) {
        List<Logistics> data = CSV2RedisUtils.parseCSVFile(file);
        data.forEach(obj -> {
            double longitude = obj.getLongitude().doubleValue();
            double latitude = obj.getLatitude().doubleValue();
            String logisticsName = obj.getLogisticsName();
            geoAdd(LOGISTICS_KEY, longitude, latitude, logisticsName);
        });
    }

接口的完整代码:

    // 展现周围所有地点信息
    @RequestMapping("/showLogisticsAround")
    public Result showLogisticsAround(double lon, double lat,Double minDistanceKm,Double maxDistanceKm){
//        String member = "广东省广州市荔湾区大沙河桥";
//        double radius = 9.0;
        if (minDistanceKm == null || maxDistanceKm == null) {
            throw new IllegalArgumentException("minDistanceKm and maxDistanceKm must not be null");
        }
        Object aroundMember = location2RedisService.geoRadiusByMember(LOGISTICS_KEY,
                lon,
                lat,
                minDistanceKm,
                maxDistanceKm,
                Metrics.KILOMETERS,
                RedisGeoCommands.GeoRadiusCommandArgs
                        .newGeoRadiusArgs()
                        .includeCoordinates()
                        .includeDistance()
                        .limit(12)
                        .sortAscending()
        );
        return Result.success(aroundMember);
    }

前端页面效果:

 

  • 26
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis是一款基于内存的NoSQL数据库,具有高速读写、支持多种数据结构、分布式等优点。Redis地图聚合数据示例代码是一种使用Redis实现的网格聚合算法,能够对经纬度数据进行聚合,实现地图上的数据可视化和统计。 具体实现步骤如下: 1. 创建Redis数据结构:使用Redis的有序集合(set)数据结构,将经纬度数据转化为定点数,并保存在有序集合中,同时将数据的ID作为有序集合中的分值。 2. 确定网格大小:根据地图的缩放级别和网格聚合算法的需要,确定每个网格的大小(宽度和高度)。可以根据经纬度数据的分布情况和需要展示的精度等因素灵活调节。 3. 确定网格对应的键名:为每个网格赋予一个唯一的键名。可以使用类似“grid:row:column”的格式,并采用哈希表(hash)数据结构进行存储。 4. 数据聚合:将有序集合中的经纬度数据依次进行聚合。对每个数据点计算其所在的网格的行数和列数,通过拼接键名,得到网格对应的哈希键值,将数据ID和分值存入哈希表中。 5. 数据展示:网格聚合算法可以实现在地图上显示聚合数据的热力图效果。可以使用类似Google Maps APIs的地图API,在前端实现聚合数据的可视化效果。 此外还可以根据具体应用需要,添加更多的功能和优化,如动态聚合、异步存储等。 通过使用Redis地图聚合数据示例代码的方式,可以快速、简便地实现大数据量的经纬度数据聚合,支持多种应用场景,如人流、车流、商业活动等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值