天天看点

Redsi通过geo计算距离

一. 前言

前段时间,小熙赶项目比较忙。趁此机会记录下遇到的后端距离计算实现,app端会有实时的经纬度回传到Redis中,PC端和H5需要实时查看位置和距离,所以想下Redis是否支持此类计算。

二. Redis的geo介绍

  1. 版本支持:
    redis在3.2版本中开始支持geo功能
               
  2. 命令介绍:

    (1) geoadd 添加地址

    sms-center:5>geoadd cityLocationGeo 116.405285 39.904989 北京
     1
    
      sms-center:5>geoadd cityLocationGeo 121.472644 31.231706 上海
     1
               
    (2)geodist 计算距离(默认是米,可以指定单位千米)
    sms-center:5>geodist cityLocationGeo 北京 上海
      1067597.9668
    
      sms-center:5>geodist cityLocationGeo 北京 上海 km
      1067.5980
               
    (3)geohash 获取地址的hash值(可用于判断是否存在)
    sms-center:5>geohash cityLocationGeo 上海 北京
       wtw3sjt9vg0
       wx4g0b7xrt0
               
    (4)geopos 获取地理位置(经纬度)
    sms-center:5>geopos cityLocationGeo 北京
        1) "116.40528291463851929"
        2) "39.9049884229125027"
               
    (5)zrem 删除某个地址(redis中没有geodel命令)
    sms-center:5>zrem cityLocationGeo 北京
         1
               

其他更多详细命令请查询文档

三. redisTemplate 使用 geo

这里的storeKey和memberKey是两个地理位置的keyName,可任意替换。

  1. 添加geo
    /**
         * 向redis中添加geo计算数据
         *
         * @param prefixName
         * @param caseDetail
         * @param latitude
         * @param longitude
         * @param name
         * @return
         */
        private String addGeoData(String prefixName, CaseDetail caseDetail, String latitude, String longitude, String name) {
            String geoKey = prefixName + "_" + caseDetail.getStoreNo() + "_" + caseDetail.getCaseNo() + "_LatitudeAndLongitude";
            Point point = new Point(Double.valueOf(longitude), Double.valueOf(latitude));
            redisTemplate.opsForGeo()
                .add(geoKey, point, name);
            redisTemplate.expire(geoKey, 30, TimeUnit.SECONDS);
         return geoKey;
      }
               
  2. 计算距离
    // 计算距离
         Distance distance = redisTemplate.boundGeoOps(geoKey).distance(storeKey, memberKey, RedisGeoCommands.DistanceUnit.KILOMETERS);
         double value = distance.getValue();
               
  3. 获取hash地址
  4. 获取地理位置(经纬度)
    List<Point> position = (List<Point>) redisTemplate.boundGeoOps(geoKey).position(memberKey)
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList()); 
               
  5. 删除某个地理位置

四. 后语

基本开发以上的可以了,如果想了解更多,可以查看文档。

继续阅读