Redis GEO地理位置信息的应用

  • Redis GEO
    • 概述
    • 应用场景
    • Redis GEO命令
    • GEO命令演示
  • Redis GEO实现附近人的功能
    • 基础类
    • API接口
    • 接口实现
    • 执行测试

Redis GEO

概述

Redis的GEO操作是一种基于地理位置信息进行操作的功能。它使用经度和纬度坐标来表示地理位置,支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能。

应用场景

地理围栏:通过设置地理位置的经纬度信息,可以将用户或者车辆等实体绑定在地理围栏内,当实体进出围栏时,可以触发相应的事件。附近的人:在类似于约会、社交、旅游等场景下,可以通过Redis GEO快速查询周围的人员或景点。配送服务:通过获取配送地址的经纬度信息,可以找到距离最近的配送员或仓库,并对订单进行分配。地址查找:在地图应用中,可以通过Redis GEO快速查询某个地址周围的商家或服务设施。动态信息:在滴滴、Uber等打车应用中,可以实时更新车辆的位置信息,以提供更加准确的车辆推荐和路线规划服务

Redis GEO命令

1.GEOADD添加位置信息

将一个或多个指定的地理位置(经度、纬度、名称)添加到指定的键中。

GEOADD key longitude latitude member [longitude latitude member ...]

添加一个名为cities的键,并将北京、上海、广州三个城市的经纬度和名称添加到该键中

GEOADD cities  116.4074 39.9042 Beijing 121.4737 31.2304 Shanghai 113.2644 23.1291 Guangzhou

GEOADD命令对于经纬度是有要求的:

有效的经度从-180度到180度有效的纬度从-85.05112878度到85.05112878度

2.GEODIST查询距离

返回两个位置之间的距离。可以选择以米或千米为单位。

GEODIST key member1 member2 [unit]

可选参数unit用于指定计算距离时的单位:

m 表示单位为米km 表示单位为千米mi 表示单位为英里ft 表示单位为英尺

查询北京和上海之间的距离,单位为千米

GEODIST cities Beijing Shanghai km

3.GEOHASH获取指定位置的Geohash值

返回一个或多个位置的Geohash值,该值用于对地理位置进行更快速的范围查找。

GEOHASH key member [member ...]

获取北京的Geohash值

GEOHASH cities Beijing

4.GEOPOS查询地理位置坐标

返回一个或多个位置的经度和纬度。

GEOPOS key member [member ...]

查询广州的经纬度

GEOPOS cities Guangzhou

5.GEORADIUS查找指定范围内的元素

查询给定坐标范围内的所有元素。可以通过设置排序选项来获取按距离排序的结果。

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [ASC|DESC] [COUNT count]

查找距离北京1000公里以内的城市,并按距离升序排列

GEORADIUS cities 116.4074 39.9042 1000 km ASC

6.GEORADIUSBYMEMBER查询给定成员周围的所有元素

查询给定成员周围的所有元素。可以通过设置排序选项来获取按距离排序的结果。

GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [ASC|DESC] [COUNT count]

查找距离上海最近的城市,并返回它们的名称和距离

GEORADIUSBYMEMBER cities Shanghai 100 km WITHDIST

7.ZREM删除成员

从指定键中删除一个或多个成员。

ZREM key member [member ...]

从cities键中删除广州

ZREM cities Guangzhou

GEO命令演示

# 添加位置信息
本机:0>geoadd user:location 121.48941  31.40527 'shagnhai'
"1"
# 添加多个位置信息
本机:0>geoadd user:location 121.47941 31.41527 'shanghai1'  121.47941 31.43527 'shagnhai2'  121.47941 31.40527 'shagnhai3'
"3"# 计算距离,单位有m km ft(英尺) mi(英里)
# 计算两点间的距离,单位m
本机:0>geodist user:location shanghai shanghai1 m
"1462.1834"
# 千米:km
本机:0>geodist user:location shanghai shanghai1 km
"1.4622"# geohash 返回一个或多个位置元素的geohash,保存Redis中是用geohash位置52点整数编码
# geohash 将二维经纬度转换成字符串,每个字符串代表一个矩形区域,该矩形区域内的经纬度点都共享一个相同的geohash字符串。
本机:0>geohash user:location shanghai shanghai1
1) "wtw6st1uuq0"
2) "wtw6sqfx5q0"# geopos 从key里返回指定成员的位置信息
本机:0>geopos user:location shanghai shanghai1
1) 1) "121.48941010236740112"2) "31.40526993848380499"2) 1) "121.47941082715988159"2) "31.41526941345740198"# georadius:给定经纬度为中心,返回键包含的位置元素中,与中心的距离不超过给定最大距离的所有位置元素
# 范围单位:m km mi ft
# withcoord:将位置元素的经纬度一并返回
本机:0>georadius user:location 121.48941 31.40527 3000 m withcoord
1) 1) "shagnhai3"2) 1) "121.47941082715988159"2) "31.40526993848380499"2) 1) "shanghai1"2) 1) "121.47941082715988159"2) "31.41526941345740198"3) 1) "shanghai"2) 1) "121.48941010236740112"2) "31.40526993848380499"# withdist:返回位置元素的同时,将位置元素与中心点间的距离一并返回
本机:0>georadius user:location 121.48941 31.40527 3000 m withdist
1) 1) "shagnhai3"2) "949.2411"2) 1) "shanghai1"2) "1462.1719"3) 1) "shanghai"2) "0.0119"# asc:根据中心位置,按照从近到远的方式返回位置元素
本机:0>georadius user:location 121.48941 31.40527 3000 m withdist asc
1) 1) "shanghai"2) "0.0119"2) 1) "shagnhai3"2) "949.2411"3) 1) "shanghai1"2) "1462.1719"# desc: 根据中心位置,按照从远到近的方式返回位置元素
本机:0>georadius user:location 121.48941 31.40527 3000 m withdist desc
1) 1) "shanghai1"2) "1462.1719"2) 1) "shagnhai3"2) "949.2411"3) 1) "shanghai"2) "0.0119"# count:获取指定数量的元素
本机:0>georadius user:location 121.48941 31.40527 3000 m withdist desc count 2
1) 1) "shanghai1"2) "1462.1719"2) 1) "shagnhai3"2) "949.2411"# georadiusbymember:和georadius命令类似,都可以找出指定位置范围内的元素,但是georadiusbymember的中心点是由给定位置元素决定的,而不像georadius使用经纬度决定中心点
本机:0>georadiusbymember user:location shanghai 3 km
1) "shagnhai3"
2) "shanghai1"
3) "shanghai"

Redis GEO实现附近人的功能

基础类

创建NearMeUserVO视图对象,封装响应视图的基本数据信息

@Data
public class NearMeUserVO {public Integer id;/*** 距离*/public String distance;
}

创建User对象模拟操作用户

    @Datapublic class User {private  int id;}

API接口

创建添加、更新用户位置信息查询附近用户信息的2个API接口

@RestController
public class NearMeUserController {@Autowiredprivate INearMeUserService nearMeUserService;/*** 添加、更新坐标** @param lon* @param lat* @return*/@PostMapping("/updateUserLocation")public String updateUserLocation(@RequestParam Float lon, @RequestParam Float lat) {nearMeUserService.updateUserLocation(lon, lat);return "OK";}/*** 获取附近的人* 查询距离指定经纬度一定范围内的用户,并返回结果列表** @param radius* @param lon* @param lat* @return*/@GetMapping("/getNearMe")public Object nearMe(Integer radius, Float lon, Float lat) {List<NearMeUserVO> nearMe = nearMeUserService.findNearMe(radius, lon, lat);return nearMe;}
}

接口实现

public interface INearMeUserService {/*** 更新坐标** @param lon 经度* @param lat 纬度*/void updateUserLocation(Float lon, Float lat);/*** 获取附近的人** @param radius 半径,默认 1000m* @param lon    经度* @param lat    纬度* @return*/List<NearMeUserVO> findNearMe(Integer radius, Float lon, Float lat);
}
@Service
public class NearMeUserServiceImpl implements INearMeUserService {@Autowiredprivate RedisTemplate<Object, Object> redisTemplate;/*** 用户定位信息cKEY*/private static final String USER_LOCATION_KEY = "user:location";public void updateUserLocation(Float lon, Float lat) {if (lon == null || lat == null) {throw new RuntimeException("获取经度、维度失败");}// 获取登录用户信息User user = this.getLoginUser();// 定义keyString key = "user:location";// 将用户地理位置信息存入 RedisRedisGeoCommands.GeoLocation geoLocation = new RedisGeoCommands.GeoLocation(user.getId(), new Point(lon, lat));redisTemplate.opsForGeo().add(key, geoLocation);}/*** 获取附近的人** @param radius 半径,默认 1000m* @param lon    经度* @param lat    纬度* @return*/public List<NearMeUserVO> findNearMe(Integer radius, Float lon, Float lat) {// 获取登录用户信息User user = this.getLoginUser();int userId = user.getId();// 处理半径,默认 1000mif (radius == null) {radius = 1000;}// 获取用户经纬度Point point = null;if (lon == null || lat == null) {// 如果经纬度没传,那么从 Redis 中获取List<Point> points = redisTemplate.opsForGeo().position(USER_LOCATION_KEY, userId);if (points == null || points.isEmpty()) {throw new RuntimeException("获取经纬度失败");}point = points.get(0);} else {point = new Point(lon, lat);}// 初始化距离对象,单位 mDistance distance = new Distance(radius, RedisGeoCommands.DistanceUnit.METERS);// 初始化 Geo 命令参数对象RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();// 附近的人限制3,包含距离,按由近到远排序args.limit(3).includeDistance().sortAscending();// 以用户经纬度为圆心,范围 1000mCircle circle = new Circle(point, distance);// 获取附近的人 GeoLocation 信息GeoResults<RedisGeoCommands.GeoLocation<Object>> geoResult = redisTemplate.opsForGeo().radius(USER_LOCATION_KEY, circle, args);// 构建有序 MapMap<Integer, NearMeUserVO> nearMeUserVOMap = Maps.newLinkedHashMap();// 完善用户信息geoResult.forEach(result -> {RedisGeoCommands.GeoLocation<Object> geoLocation = result.getContent();// 初始化Vo对象NearMeUserVO nearMeUserVO = new NearMeUserVO();nearMeUserVO.setId((Integer) geoLocation.getName());// 获取距离Double dist = result.getDistance().getValue();// 四舍五入精确到小数点后 1 位,方便客户端显示String distanceStr = NumberUtil.round(dist, 1).toString() + "m";nearMeUserVO.setDistance(distanceStr);nearMeUserVOMap.put((Integer) geoLocation.getName(), nearMeUserVO);});// 附近的人,可进一步完善用户信息
//        Integer[] userIds = nearMeUserVOMap.keySet().toArray(new Integer[0]);ArrayList<NearMeUserVO> nearMeUserVO = Lists.newArrayList(nearMeUserVOMap.values());return nearMeUserVO;}/*** 模拟获取真实登录用户信息** @return*/public User getLoginUser() {User user = new User();user.setId(1);return user;}
}

执行测试

访问执行添加用户地理位置数据接口,得到如下所示数据:


访问执行获取附近人接口,得到如下所示数据:

 "data": [{"id": 1,"distance": "0.0m"},{"id": 3,"distance": "949.3m"},{"id": 2,"distance": "1462.2m"}]

Redis GEO地理位置信息的应用相关推荐

  1. redis:地理位置信息geo

    简介 redis3.2版本提供了GEO(地理信息定位)功能,支持存储地理位置信息. 可以用来实现比如附近位置,摇一摇这类依附于地理位置的功能 GEO功能是 Redis 的另一位作者Matt Stanc ...

  2. java redis geo_redis学习计划(九)redis GEO地理位置

    redis目前已经到了3.2版本,3.2版本里面新增的一个功能就是对GEO(地理位置)的支持. 地理位置大概提供了6个命令,分别为: GEOADD GEODIST GEOHASH GEOPOS GEO ...

  3. 基于Redis GEO(地理位置) 实现附近的人,商家等相关功能实现 使用SpringBoot Redis工具类

    Redis GEO 1.基本介绍 1.Redis GEO 2.基础语法 GEOADD GEOPOS GEODIST GEORADIUS GEOHASH 2.可用于实现的功能 3.SpringBoot实 ...

  4. [LBS学习笔记3]redis geo地理位置查询分析

    1.redis geo命令 1.1 redis6.2版本geo命令简介 redis自3.2版本开始,提供了地理位置相关的命令: GEOADD:添加空间元素 GEOPOS: 获取某个地理位置的坐标 GE ...

  5. redis 附近的人_Redis GEO地理位置信息,查看附近的人

    在之前的一篇文章<SpringBoot入门教程(五)Java基于MySQL实现附近的人>,我们介绍了Java基于MySQL实现查找附近的人的功能.今天就来研究研究"查找附近的人& ...

  6. Redis之GEO存储地理位置信息

    在外卖软件中的附近的美食店铺.外卖小哥的距离,打车软件附近的车辆,交友软件中附近的小姐姐.我们都可以利用redis的GEO地理位置计算得出. 1.Redis 的 Geo 是在 3.2 版本才有的 2. ...

  7. redis学习--三种特殊数据类型,GEO地理位置,HyperLogLog,BitMap

    三种特殊数据类型,GEO地理位置,HyperLogLog,BitMap GEO地理位置 简介 Redis 的 GEO 特性在 Redis 3.2 版本中推出, 这个功能可以将用户给定的地理位置信息储存 ...

  8. redis 的geo地理位置及实现附近的人的功能

    前言 redis在3.2版本里面新增的一个功能就是对GEO(地理位置)的支持. 理位置大概提供了6个命令,分别为: GEOADD GEODIST GEOHASH GEOPOS GEORADIUS GE ...

  9. Geo Location 地理位置信息小结

    周末调研了一下Geo Location 地理位置信息方面的内容,自己小结一下. 一.通过 IP 地址获得用户的地理位置信息 也就是根据用户的IP,通过IP数据库查询获得信息.一般IP数据库中, 每条记 ...

最新文章

  1. 鲍尔默说:你的东西再大 微软也装得下
  2. tomcat压力测试、优化
  3. html5 将id的值用于top_web前端分享HTML5常见面试题集锦四
  4. 15 | 二分查找(上):如何用最省内存的方式实现快速查找功能?
  5. 原linux的字符文件作用,linux特殊字符及其作用大全
  6. java三年技术差_3年经验Java程序员面阿里P6 差距在哪里
  7. PYPL 1 月 IDE 榜单:Visual Studio Code 猛追 IntelliJ
  8. centos 6.2安装mysql_centos6.2安装mysql
  9. [转载] python-TypeError: Object of type ‘Decimal‘ is not JSON serializable 报错
  10. SIR模型的应用(2) - Influence maximization in social networks based on TOPSIS(3)
  11. 应该根据哪些判断云服务器的好坏
  12. Playing games
  13. 量子信息-学习记录13
  14. 从iPhone6S发售谈富士康电商富连网
  15. VC++获取系统当前时间并显示
  16. 在深度OS中编译MRtrix步骤
  17. 红牛的广告:你的能量超乎你的想象
  18. certbot为NGINX配置SSL证书
  19. 封禁135、137、139、445端口
  20. Ruby 日期和时间(和 Python3 日期和时间对比)

热门文章

  1. Pikachu靶场之文件上传漏洞详解
  2. web前端之初级html-学习笔记分享一
  3. markdown表格快捷键
  4. Core Animation核心动画的使用
  5. 【软件生命周期各个阶段详解】
  6. 我现在正在构建一个神经网络模型,需要用来解决判断晶体材料的声子谱是否有虚频这个问题...
  7. WPF Window 窗口获得焦点和失去焦点事件
  8. Redis笔记-入门篇
  9. 2022中国国际塑料展主办单位已被法院列为老赖
  10. 打印1000---2000年的闰年并计算闰年的个数