一. 前言
前段時間,小熙趕項目比較忙。趁此機會記錄下遇到的後端距離計算實作,app端會有實時的經緯度回傳到Redis中,PC端和H5需要實時檢視位置和距離,是以想下Redis是否支援此類計算。
二. Redis的geo介紹
- 版本支援:
redis在3.2版本中開始支援geo功能
-
指令介紹:
(1) geoadd 添加位址
(2)geodist 計算距離(預設是米,可以指定機關千米)sms-center:5>geoadd cityLocationGeo 116.405285 39.904989 北京 1 sms-center:5>geoadd cityLocationGeo 121.472644 31.231706 上海 1
(3)geohash 擷取位址的hash值(可用于判斷是否存在)sms-center:5>geodist cityLocationGeo 北京 上海 1067597.9668 sms-center:5>geodist cityLocationGeo 北京 上海 km 1067.5980
(4)geopos 擷取地理位置(經緯度)sms-center:5>geohash cityLocationGeo 上海 北京 wtw3sjt9vg0 wx4g0b7xrt0
(5)zrem 删除某個位址(redis中沒有geodel指令)sms-center:5>geopos cityLocationGeo 北京 1) "116.40528291463851929" 2) "39.9049884229125027"
sms-center:5>zrem cityLocationGeo 北京 1
其他更多詳細指令請查詢文檔
三. redisTemplate 使用 geo
這裡的storeKey和memberKey是兩個地理位置的keyName,可任意替換。
- 添加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; }
- 計算距離
// 計算距離 Distance distance = redisTemplate.boundGeoOps(geoKey).distance(storeKey, memberKey, RedisGeoCommands.DistanceUnit.KILOMETERS); double value = distance.getValue();
- 擷取hash位址
- 擷取地理位置(經緯度)
List<Point> position = (List<Point>) redisTemplate.boundGeoOps(geoKey).position(memberKey) .stream() .filter(Objects::nonNull) .collect(Collectors.toList());
- 删除某個地理位置
四. 後語
基本開發以上的可以了,如果想了解更多,可以檢視文檔。