Redis GEO地理位置信息的应用

这篇具有很好参考价值的文章主要介绍了Redis GEO地理位置信息的应用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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对象模拟操作用户

    @Data
    public class User {
        private  int id;
    }

API接口

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

@RestController
public class NearMeUserController {
    @Autowired
    private 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 {

    @Autowired
    private 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();
        // 定义key
        String key = "user:location";

        // 将用户地理位置信息存入 Redis
        RedisGeoCommands.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();

        // 处理半径,默认 1000m
        if (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);
        }

        // 初始化距离对象,单位 m
        Distance distance = new Distance(radius, RedisGeoCommands.DistanceUnit.METERS);
        // 初始化 Geo 命令参数对象
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        // 附近的人限制3,包含距离,按由近到远排序
        args.limit(3).includeDistance().sortAscending();
        // 以用户经纬度为圆心,范围 1000m
        Circle circle = new Circle(point, distance);
        // 获取附近的人 GeoLocation 信息
        GeoResults<RedisGeoCommands.GeoLocation<Object>> geoResult = redisTemplate.opsForGeo().radius(USER_LOCATION_KEY, circle, args);

        // 构建有序 Map
        Map<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;
    }
}

执行测试

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

Redis GEO地理位置信息的应用
访问执行获取附近人接口,得到如下所示数据:文章来源地址https://www.toymoban.com/news/detail-481760.html

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

到了这里,关于Redis GEO地理位置信息的应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 探索Redis特殊数据结构:Geospatial(地理位置)在实际中的应用

    Redis官方提供了多种数据类型,除了常见的String、Hash、List、Set、zSet之外,还包括Stream、Geospatial、Bitmaps、Bitfields、Probabilistic(HyperLogLog、Bloom filter、Cuckoo filter、t-digest、Top-K、Count-min sketch、Configuration)和Time series。这些数据类型在Redis的数据结构中发挥着各自独特的作用。

    2024年02月20日
    浏览(32)
  • Unity 获取手机地理位置信息

    在游戏的开发过程中,有时候会遇到需要获取玩家位置信息的需求,比如显示玩家所在的国家城市等。 有一下方法可以参考: 可以根据手机的地区和语言来做判断。 根据IP来判断所处的位置,阿里云啥的都有对应的接口服务。 根据GPS来判断。 以上方法都各有利弊吧,这里简

    2024年02月12日
    浏览(36)
  • 通过ip获取地理位置信息

    GeoLite2-City.mmdb 文件是 MaxMind 公司提供的一个免费的 IP 地址与城市地理位置映射数据库文件。它包含了 IP 地址范围与对应的城市、地区、国家、经纬度等地理位置信息的映射。这种数据库文件可以用于识别访问您的应用程序或网站的用户的地理位置,从而实现针对不同地区的

    2024年02月12日
    浏览(32)
  • Golang — 根据IP获取地理位置信息

    1 ip2region 2 geoip2-golang ip2region 是一个离线IP地址定位库和IP定位数据管理框架,10微秒级别的查询效率,提供了众多主流编程语言的 xdb 数据生成和查询客户端实现。 特点: 是一个开源的IP地理位置库。 标准化的数据格式 每个 ip 数据段的 region 信息都固定了格式:国家|区域|省

    2024年02月14日
    浏览(32)
  • uniapp h5获取用户地理位置信息(高德地图)

     使用uni.getLocation()先获取到当前位置信息的经纬度 H5端测试可以使用http,上线打包需要设置为https模式 谷歌浏览器可能会获取不到任何信息,因为谷歌浏览器位置信息是连接谷歌服务器获取的,国内用户可能获取位置信息失败 使用高德开发平台注册一个key 高德开发平台:高

    2024年02月13日
    浏览(34)
  • (Java版)根据ip获取地理位置以及相关信息

    1.首先我们需要进入地图开放平台的官网,根据提示注册账号,以百度地图为例: https://lbsyun.baidu.com/ 我们新用户登录之后会弹出这个页面,选择个人爱好者进入完成注册 成功之后我们会进入到下面这个页面,如果没有申请ak的小伙伴在控制台看板这一块是有一个流程指引的

    2024年02月08日
    浏览(22)
  • IP详细地理位置查询:技术原理与应用实践

    IP地址是互联网上设备的唯一标识,在网络安全、个性化服务等领域具有重要意义。通过IP详细地理位置查询,可以获取到IP地址所在地的具体信息,为网络管理、定位服务等提供支持。IP数据云将深入探讨IP详细地理位置查询的技术原理、应用实践以及相关的隐私安全考虑,以

    2024年02月21日
    浏览(35)
  • 微信小程序通过startLocationUpdate,onLocationChange获取当前地理位置信息,配合腾讯地图解析获取到地址

    先创建个getLocation.js文件 在App.vue文件里引入封装的getLocation.js文件 要在manifest.json文件里配置下内容

    2024年02月03日
    浏览(41)
  • APP应用加固指南:如何有效辨别,网络上伪造的地理位置?

    在数字互联时代,已经离不开地理位置数据。地理位置数据不仅仅是一个简单的坐标,更是一种数字足迹,描绘了人们在数字世界中的实际存在。这些数据为我们提供了关键的背景信息,让人们在享受数字服务的同时,也能更好地理解人们的生活环境。     首先,基于地理位

    2024年02月04日
    浏览(36)
  • Java编程技巧:获取ip地址、通过ip获取地理位置、获取客户端操作系统、获取客户端浏览器、获取主机名、获取操作系统、获取系统架构

    说明: 大家直接去对应项目位置找到代码,然后看着复制就行了 1.1、若依(自己写的代码) 项目:https://gitee.com/y_project/RuoYi 子模块:ruoyi-common 所在类:com.ruoyi.common.utils.IpUtils 所在方法:getIpAddr 详细位置:整个方法 1.2、Snowy(借助hutool工具包) 项目:https://gitee.com/xiaonuo

    2024年02月04日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包