一. 前言
前段时间,小熙赶项目比较忙。趁此机会记录下遇到的后端距离计算实现,app端会有实时的经纬度回传到Redis中,PC端和H5需要实时查看位置和距离,所以想下Redis是否支持此类计算。
二. Redis的geo介绍
-
版本支持:
redis在3.2版本中开始支持geo功能
-
命令介绍:
(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,可任意替换。
-
添加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 hash = redisTemplate.boundGeoOps(geoKey).hash(storeKey);
-
获取地理位置(经纬度)
List<Point> position = (List<Point>) redisTemplate.boundGeoOps(geoKey).position(memberKey) .stream() .filter(Objects::nonNull) .collect(Collectors.toList());
-
删除某个地理位置
Long remove = redisTemplate.boundGeoOps(geoKey).remove(storeKey);
四. 后语
基本开发以上的可以了,如果想了解更多,可以查看文档。