redis-geo

前言

在涉及到经纬度定位点操作的时候,我们了解了GEO的概念

我们有时候也需要根据经纬度点进行一些业务开发,比如根据自己当前定位获取最近商家(美团)、获取最近车辆(打车软件)获取两个地点之间的距离等,这个时候,我们便可以使用redis中geo来简化我们的业务代码开发。

image-20230522200753820

但实际上,redis-geo并不是一种全新的数据结构,其底层是sorted set

redis-geo相关命令

image-20230522201343816

详细内容则可以直接参考官网: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)));

image-20230522204216524

image-20230522205000944

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());

image-20230522204452888

image-20230522204522387

GEOHASH

GeoHash编码转换后的11位字符串表示形式

List<String> hash = redisTemplate.opsForGeo().hash("geo", "九里堤农贸");
// [wm6n8h9sef0]
System.out.println(hash);

粘贴至网站

http://geohash.org/你的转码后的字符串

ex:

http://geohash.org/wm6n8h9sef0

image-20230522210046539

返回上边查看我们九里堤农贸定位点信息

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, ]]

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐