redis-geo
前言
在涉及到经纬度定位点操作的时候,我们了解了GEO的概念
我们有时候也需要根据经纬度点进行一些业务开发,比如根据自己当前定位获取最近商家(美团)、获取最近车辆(打车软件)获取两个地点之间的距离等,这个时候,我们便可以使用redis中geo来简化我们的业务代码开发。
但实际上,redis-geo并不是一种全新的数据结构,其底层是sorted set
redis-geo相关命令
详细内容则可以直接参考官网:https://redis.io/commands/?group=geo
GEOADD
版本要求:3.2.0
将指定的空间元素(经度、纬度、元素名)添加到key对应的Sorted Set中
GEODIST
版本要求:3.2.0
返回两个给定元素之间的距离,距离支持 千米 米 英尺 英里
GEOHASH
版本要求:3.2.0
- GEOADD命令会将经纬度编码为52bit,该命令返回GeoHash编码转换后的
11
位字符串表示形式,该字符串形式,与 **维基百科**描述一致,兼容 **geohash.org**规范 - 使用该URL: http://geohash.org/,可以反向解析出命令返回的11位字符串对应的经纬度,例如http://geohash.org/wm6n8h9sef0。页面中显示对应的纬度和经度(九里堤农贸附近)
GEOPOS
版本要求:3.2.0
返回给定元素对应的经纬度 (使用GEOADD添加的元素,会被GeoHash转化为52位比特值,因此使用GEOPOS取出值并转为经纬度时,可能与添加的经纬度值有少许差异)
GEORADIUS
版本要求:3.2.0
指定元素的经纬度与半径(米 米 英尺 英里)得到一个圆形区域,返回圆形区域中的所有元素
GEORADIUSBYMEMBER
版本要求:3.2.0
指定元素与半径(米 米 英尺 英里)得到一个圆形区域,返回圆形区域中的所有元素
springboot整合
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
GEOADD
添加定位点元素至集合
point 包路径:org.springframework.data.geo.Point
redisTemplate.opsForGeo().add("geo", new Point(104.063037, 30.701011), "九里堤");
或
org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation#GeoLocation
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("北站西", new Point(104.072595, 30.700887)));
redisTemplate().add("geo", new RedisGeoCommands.GeoLocation<>("北站西", new Point(104.072595, 30.700887)));
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("九里堤农贸", new Point(104.064726, 30.699334)));
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("西北桥", new Point(104.064007, 30.692037)));
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("城北派出所", new Point(104.073386, 30.702136)));
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("人民北路", new Point(104.078345, 30.692168)));
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("哈啰酒店-成都西南交大店", new Point(104.052828, 30.699939)));
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("矮冬瓜红茶火锅", new Point(104.052936, 30.698899)));
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("沈跃全中医", new Point(104.052199, 30.698231)));
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("五丁小学", new Point(104.067169, 30.695763)));
redisTemplate.opsForGeo().add("geo", new RedisGeoCommands.GeoLocation<>("那屋网客", new Point(104.061456, 30.700576)));
GEODIST
获取指定两个元素间的距离 默认是m单位
Distance distance = redisTemplate.opsForGeo().distance("geo", "九里堤", "北站西");
Distance distance2 = redisTemplate.opsForGeo().distance("geo", "九里堤", "北站西", RedisGeoCommands.DistanceUnit.KILOMETERS);
// 913.8254 m
System.out.println(distance.getValue() + " " + distance.getUnit());
// 0.9138 km
System.out.println(distance2.getValue() + " " + distance2.getUnit());
GEOHASH
GeoHash编码转换后的11
位字符串表示形式
List<String> hash = redisTemplate.opsForGeo().hash("geo", "九里堤农贸");
// [wm6n8h9sef0]
System.out.println(hash);
粘贴至网站
http://geohash.org/你的转码后的字符串
ex:
http://geohash.org/wm6n8h9sef0
返回上边查看我们九里堤农贸
定位点信息
GEOPOS
返回给定元素的经纬度信息(可能会有损耗)
List<Point> position = redisTemplate.opsForGeo().position("geo", "九里堤", "北站西");
// [Point [x=104.063039, y=30.701010], Point [x=104.072593, y=30.700886]]
System.out.println(position);
GEORADIUS
指定元素的经纬度与半径(米 米 英尺 英里)得到一个圆形区域,返回圆形区域中的所有元素
// 以指定元素(我这里是九里堤)为圆心,获取指定半径范围内的数据 (包含自身)
Circle circle = new Circle(new Point(104.063037, 30.701011), new Distance(1000, RedisGeoCommands.DistanceUnit.METERS));
GeoResults<RedisGeoCommands.GeoLocation<Object>> radius = redisTemplate.opsForGeo().radius("geo", circle);
结果
[GeoResult [content: RedisGeoCommands.GeoLocation(name=九里堤, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=北站西, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=城北派出所, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=五丁小学, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=九里堤农贸, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=那屋网客, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=矮冬瓜红茶火锅, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=哈啰酒店-成都西南交大店, point=null), distance: 0.0, ]]
GEORADIUSBYMEMBER
指定元素与半径(米 米 英尺 英里)得到一个圆形区域,返回圆形区域中的所有元素
GeoResults<RedisGeoCommands.GeoLocation<Object>> radius = redisTemplate.opsForGeo().radius("geo", "九里堤", 1000);
System.out.println(new ArrayList<>(radius.getContent()));
结果
[GeoResult [content: RedisGeoCommands.GeoLocation(name=九里堤, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=北站西, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=城北派出所, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=五丁小学, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=九里堤农贸, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=那屋网客, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=矮冬瓜红茶火锅, point=null), distance: 0.0, ], GeoResult [content: RedisGeoCommands.GeoLocation(name=哈啰酒店-成都西南交大店, point=null), distance: 0.0, ]]
定制化获取指定半径内的数据
// 定制化获取指定半径内的数据
RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
// 只获取最近的一个geo信息
geoRadiusCommandArgs.limit(1);
geoRadiusCommandArgs.includeCoordinates();
// 距给定经纬度由远及近的顺序
geoRadiusCommandArgs.sort(Sort.Direction.DESC);
// 指定圆心点、半径大小、距离单位
GeoResults<RedisGeoCommands.GeoLocation<Object>> radius2 = redisTemplate.opsForGeo().radius("geo", "九里堤",
new Distance(1, RedisGeoCommands.DistanceUnit.KILOMETERS), geoRadiusCommandArgs);
System.out.println(new ArrayList<>(radius2.getContent()));
[GeoResult [content: RedisGeoCommands.GeoLocation(name=城北派出所, point=Point [x=104.073387, y=30.702136]), distance: 0.0 KILOMETERS, ]]