由于最近项目中需要用到距离计算, 附近位置等功能, 就想到redis了的GeoHash, 关于GeoHash的概念就不过多介绍, 用法也比较简单, 但由于项目中使用的是Redission, 网上有关Redission 使用GeoHash的工具类也非常之少, 无奈只能自己动手写了。
话不多说,直接上工具类, 做了两层封装。
一.RedissonTemplate
/**
* 操作对象
*/
public class RedissonTemplate {
@Resource
private RedissonClient redissonClient;
private static RedissonTemplate redissonTemplate;
public static RedissonTemplate getInstance() {
if (redissonTemplate == null) {
redissonTemplate = SpringUtils.getBean(RedissonTemplate.class);
}
return redissonTemplate;
}
/**
* sortedSet删除元素
*
* @param name
* @param o
* @return
*/
public boolean zrem(String name, Object o) {
RScoredSortedSet<Object> scoredSortedSet = redissonClient.getScoredSortedSet(name);
return scoredSortedSet.remove(o);
}
/**
* 将指定的地理空间位置(纬度、经度、名称)添加到指定的key中
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param member 成员名称
* @return 添加元素个数
*/
public Long geoAdd(String name, double lng, double lat, Object member) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.add(lng, lat, member);
}
/**
* 返回两个给定位置之间的距离
*
* @param name 集合名称
* @param firstMember 第一个成员
* @param secondMember 第二个成员
* @param geoUnit 返回距离单位
* @return
*/
public Double geoDist(String name, Object firstMember, Object secondMember, GeoUnit geoUnit) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.dist(firstMember, secondMember, geoUnit);
}
/**
* 从key里返回所有给定位置元素的位置(经度和纬度)
*
* @param name 集合名称
* @param members 成员
* @return
*/
public Map<Object, GeoPosition> geoPos(String name, Object... members) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.pos(members);
}
/**
* 返回一个或多个位置元素的 Geohash 表示
*
* @param name 集合名称
* @param members 成员
* @return
*/
public Map<Object, String> geoHash(String name, Object... members) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.hash(members);
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 单位
* @return
*/
public List<Object> geoRadius(String name, double lng, double lat, double radius, GeoUnit geoUnit) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radius(lng, lat, radius, geoUnit);
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 单位
* @param count 返回元素个数
* @return
*/
public List<Object> geoRadius(String name, double lng, double lat, double radius, GeoUnit geoUnit, int count) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radius(lng, lat, radius, geoUnit, count);
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 单位
* @param geoOrder 排序规则
* @return
*/
public List<Object> geoRadius(String name, double lng, double lat, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radius(lng, lat, radius, geoUnit, geoOrder);
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 单位
* @return
*/
public List<Object> geoRadiusByMember(String name, Object member, double radius, GeoUnit geoUnit) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radius(member, radius, geoUnit);
}
/**
* 以给定的成员为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 单位
* @param count 返回元素个数
* @return
*/
public List<Object> geoRadiusByMember(String name, Object member, double radius, GeoUnit geoUnit, int count) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radius(member, radius, geoUnit, count);
}
/**
* 以给定的成员为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 单位
* @param geoOrder 排序规则
* @return
*/
public List<Object> geoRadiusByMember(String name, Object member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radius(member, radius, geoUnit, geoOrder);
}
/**
* 以给定的成员为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 单位
* @param geoOrder 排序规则
* @param count 返回元素个数
* @return
*/
public List<Object> geoRadiusByMember(String name, Object member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radius(member, radius, geoUnit, geoOrder, count);
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 半径单位
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, double lng, double lat, double radius, GeoUnit geoUnit) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radiusWithDistance(lng, lat, radius, geoUnit);
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 半径单位
* @param count 返回元素个数
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, double lng, double lat, double radius, GeoUnit geoUnit, int count) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radiusWithDistance(lng, lat, radius, geoUnit, count);
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 半径单位
* @param geoOrder 排序
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, double lng, double lat, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radiusWithDistance(lng, lat, radius, geoUnit, geoOrder);
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 半径单位
* @param geoOrder 排序
* @param count 返回元素个数
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, double lng, double lat, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radiusWithDistance(lng, lat, radius, geoUnit, geoOrder, count);
}
/**
* 以给定的成员为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 半径单位
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, Object member, double radius, GeoUnit geoUnit) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radiusWithDistance(member, radius, geoUnit);
}
/**
* 以给定的成员为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 半径单位
* @param count 返回元素个数
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, Object member, double radius, GeoUnit geoUnit, int count) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radiusWithDistance(member, radius, geoUnit, count);
}
/**
* 以给定的成员为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 半径单位
* @param geoOrder 排序
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, Object member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radiusWithDistance(member, radius, geoUnit, geoOrder);
}
/**
* 以给定的成员为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 半径单位
* @param geoOrder 排序
* @param count 返回元素个数
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, Object member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
RGeo<Object> geo = redissonClient.getGeo(name);
return geo.radiusWithDistance(member, radius, geoUnit, geoOrder, count);
}
}
二.RedisService
public class RedisService {
@Autowired
private RedissonTemplate redissonTemplate;
/**
* 移除有序集合中的一个成员
*
* @param key
* @param member
* @return
*/
public boolean zSetRemove(String key, Object member) {
try {
return redissonTemplate.zrem(key, member);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将指定的地理空间位置(纬度、经度、名称)添加到指定的key中
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param member 成员名称
* @return 添加元素个数
*/
public Long geoAdd(String name, double lng, double lat, Object member) {
try {
return redissonTemplate.geoAdd(name, lng, lat, member);
} catch (Exception e) {
e.printStackTrace();
return 0L;
}
}
/**
* 返回两个给定位置之间的距离
*
* @param name 集合名称
* @param firstMember 第一个成员
* @param secondMember 第二个成员
* @param geoUnit 返回距离单位
* @return
*/
public Double geoDist(String name, Object firstMember, Object secondMember, GeoUnit geoUnit) {
try {
return redissonTemplate.geoDist(name, firstMember, secondMember, geoUnit);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 返回两个给定位置之间的距离
*
* @param name 集合名称
* @param firstMember 第一个成员
* @param secondMember 第二个成员
* @return 返回值单位为km
*/
public Double geoDist(String name, Object firstMember, Object secondMember) {
try {
return redissonTemplate.geoDist(name, firstMember, secondMember, GeoUnit.KILOMETERS);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 从key里返回所有给定位置元素的位置(经度和纬度)
*
* @param name 集合名称
* @param members 成员
* @return
*/
public Map<Object, GeoPosition> geoPos(String name, Object... members) {
try {
return redissonTemplate.geoPos(name, members);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, GeoPosition>();
}
}
/**
* 返回给定位置元素的位置(经度和纬度)
*
* @param name 集合名称
* @param members 成员
* @return
*/
public GeoPosition geoPos(String name, Object member) {
try {
Map<Object, GeoPosition> objectGeoPositionMap = redissonTemplate.geoPos(name, new Object[]{member});
if (CollUtil.isNotEmpty(objectGeoPositionMap)) {
return objectGeoPositionMap.get(member);
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 半径单位km
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @return
*/
public List<Object> geoRadius(String name, double lng, double lat, double radius) {
try {
return redissonTemplate.geoRadius(name, lng, lat, radius, GeoUnit.KILOMETERS);
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 单位
* @return
*/
public List<Object> geoRadius(String name, double lng, double lat, double radius, GeoUnit geoUnit) {
try {
return redissonTemplate.geoRadius(name, lng, lat, radius, geoUnit);
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 单位
* @param count 返回元素个数
* @return
*/
public List<Object> geoRadius(String name, double lng, double lat, double radius, GeoUnit geoUnit, int count) {
try {
return redissonTemplate.geoRadius(name, lng, lat, radius, geoUnit, count);
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 单位
* @param geoOrder 排序规则
* @return
*/
public List<Object> geoRadius(String name, double lng, double lat, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
try {
return redissonTemplate.geoRadius(name, lng, lat, radius, geoUnit, geoOrder);
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param member 成员
* @param radius 半径(默认单位:km)
* @return
*/
public List<Object> geoRadiusByMember(String name, Object member, double radius) {
try {
return redissonTemplate.geoRadiusByMember(name, member, radius, GeoUnit.KILOMETERS);
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 单位
* @return
*/
public List<Object> geoRadiusByMember(String name, Object member, double radius, GeoUnit geoUnit) {
try {
return redissonTemplate.geoRadiusByMember(name, member, radius, geoUnit);
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
/**
* 以给定的成员为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 单位
* @param count 返回元素个数
* @return
*/
public List<Object> geoRadiusByMember(String name, Object member, double radius, GeoUnit geoUnit, int count) {
try {
return redissonTemplate.geoRadiusByMember(name, member, radius, geoUnit, count);
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
/**
* 以给定的成员为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 单位
* @param geoOrder 排序规则
* @return
*/
public List<Object> geoRadiusByMember(String name, Object member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
try {
return redissonTemplate.geoRadiusByMember(name, member, radius, geoUnit, geoOrder);
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
/**
* 以给定的成员为中心, 找出某一半径内的元素
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 单位
* @param geoOrder 排序规则
* @param count 返回元素个数
* @return
*/
public List<Object> geoRadiusByMember(String name, Object member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
try {
return redissonTemplate.geoRadiusByMember(name, member, radius, geoUnit, geoOrder, count);
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<Object>();
}
}
/**
* 返回一个或多个位置元素的 Geohash 表示
*
* @param name 集合名称
* @param member 成员
* @return Geohash值
*/
public String geoHash(String name, Object member) {
try {
Map<Object, String> objectStringMap = redissonTemplate.geoHash(name, new Object[]{member});
if (CollUtil.isNotEmpty(objectStringMap)) {
return objectStringMap.get(member);
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 返回一个或多个位置元素的 Geohash 表示
*
* @param name 集合名称
* @param members 成员
* @return
*/
public Map<Object, String> geoHash(String name, Object... members) {
try {
return redissonTemplate.geoHash(name, members);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, String>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径 默认单位:km
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, double lng, double lat, double radius) {
try {
return redissonTemplate.geoRadiusWithDistance(name, lng, lat, radius, GeoUnit.KILOMETERS);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 半径单位
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, double lng, double lat, double radius, GeoUnit geoUnit) {
try {
return redissonTemplate.geoRadiusWithDistance(name, lng, lat, radius, geoUnit);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 半径单位
* @param count 返回元素个数
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, double lng, double lat, double radius, GeoUnit geoUnit, int count) {
try {
return redissonTemplate.geoRadiusWithDistance(name, lng, lat, radius, geoUnit, count);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 半径单位
* @param geoOrder 排序
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, double lng, double lat, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
try {
return redissonTemplate.geoRadiusWithDistance(name, lng, lat, radius, geoUnit, geoOrder);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
/**
* 以给定的经纬度为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param lng 经度
* @param lat 纬度
* @param radius 半径
* @param geoUnit 半径单位
* @param geoOrder 排序
* @param count 返回元素个数
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, double lng, double lat, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
try {
return redissonTemplate.geoRadiusWithDistance(name, lng, lat, radius, geoUnit, geoOrder, count);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
/**
* 以给定的成员为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param member 成员
* @param radius 半径 默认:km
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, Object member, double radius) {
try {
return redissonTemplate.geoRadiusWithDistance(name, member, radius, GeoUnit.KILOMETERS);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
/**
* 以给定的成员为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 半径单位
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, Object member, double radius, GeoUnit geoUnit) {
try {
return redissonTemplate.geoRadiusWithDistance(name, member, radius, geoUnit);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
/**
* 以给定的成员为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 半径单位
* @param count 返回元素个数
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, Object member, double radius, GeoUnit geoUnit, int count) {
try {
return redissonTemplate.geoRadiusWithDistance(name, member, radius, geoUnit, count);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
/**
* 以给定的成员为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 半径单位
* @param geoOrder 排序
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, Object member, double radius, GeoUnit geoUnit, GeoOrder geoOrder) {
try {
return redissonTemplate.geoRadiusWithDistance(name, member, radius, geoUnit, geoOrder);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
/**
* 以给定的成员为中心, 找出某一半径内的元素, 并返回距离
*
* @param name 集合名称
* @param member 成员
* @param radius 半径
* @param geoUnit 半径单位
* @param geoOrder 排序
* @param count 返回元素个数
* @return
*/
public Map<Object, Double> geoRadiusWithDistance(String name, Object member, double radius, GeoUnit geoUnit, GeoOrder geoOrder, int count) {
try {
return redissonTemplate.geoRadiusWithDistance(name, member, radius, geoUnit, geoOrder, count);
} catch (Exception e) {
e.printStackTrace();
return new HashMap<Object, Double>();
}
}
}
三. 简单写了一些测试
@Autowired
private RedisService redisService;
@Test
public void testGeoAdd(){
redisService.geoAdd("0", 116.48105, 39.996794, 123423432L);
redisService.geoAdd("0", 116.48105, 39.996797, 234234L);
redisService.geoAdd("0", 116.489033, 40.007669, 4345435L);
Double aDouble = redisService.geoDist("0", 123423432L, 4345435L);
System.out.println(aDouble);
}
@Test
public void testGeoRadiusWithDistance(){
redisService.zSetRemove("0",123423432L);
redisService.zSetRemove("0",4345435L);
Map<Object, Double> map = redisService.geoRadiusWithDistance("0", 116.48105, 39.996795, 10.0);
Set<Object> objects = map.keySet();
for (Object object : objects) {
System.out.println(Convert.toLong(object));
}
Console.log(map);
}
四.说明
1. 相关的用法工具类上的注释应该写的比较清楚了, 需要说明的是geohash没有对应的删除方法, 由于geohash存储使用的是sorted set 数据结构, 删除方法使用sorted set中的删除方法即可