天天看點

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. 删除某個地理位置

四. 後語

基本開發以上的可以了,如果想了解更多,可以檢視文檔。

繼續閱讀