Redis GEO功能详细介绍与实战

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

一、概述

Redis的Geo功能主要用于存储地理位置信息,并对其进行操作。该功能在Redis 3.2版本新增。Redis Geo操作方法包括:

  • geoadd:添加地理位置的坐标;
  • geopos:获取地理位置的坐标;
  • geodist:计算两个位置之间的距离;
  • georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合;
  • georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合;
  • geohash:返回一个或多个位置对象的geohash值。

二、Redis Geo功能案例:

1、案例1

查找某个城市下的门店信息。
比如有的一家门店存储的Redis结构如下:

store:   
  - member: poscon  
  - member: shangxixxi

其中poscon表示该门店的坐标信息,shangxixxi表示该门店的名称。

现在需要查找某个城市下的门店信息,可以使用Redis的Geo功能实现:

GEOADD store 116.406890 39.909195 "poscon" "shangxixxi"  
GEOADD store 116.420853 39.892662 "poscon1" "shangxixxi1"  
GEOADD store 116.401415 39.915726 "poscon2" "shangxixxi2"  
GEOADD store 116.426988 39.919938 "poscon3" "shangxixxi3"  
GEOADD store 116.410057 39.904425 "poscon4" "shangxixxi4"  
GEORADIUS store 116.409729 39.908256 10000km WITHCOORD WITHDIST

以上代码表示在(116.409729, 39.908256)半径为10000km的圆内查找门店信息,返回结果会包含每个门店的坐标信息和距离。可以根据返回结果筛选出自己需要的门店信息。

2、案例2

添加下面几条数据:

  • 北京南站 ( 116.378248 39.865275
  • 北京站 ( 116.42803 39.903738 )
  • 北京西站(116.322287 39.893729 )
127.0.0.1:6379> GEOADD g1 116.378248 39.865275 bjn 116.42803 39.903738 bjz 116.322287 39.893729 bjx
(integer) 3
  1. 计算北京西站到北京站的距离
127.0.0.1:6379> GEODIST g1 bjz bjx km
"9.0916"
  1. 搜索天安门(116.397904 39.909005 )附近1km内的所有火车站,并按照距离升序排序
127.0.0.1:6379> GEOSEARCH g1 FROMLONLAT 116.397904 39.909005 BYRADIUS 10 km WITHDIST
1) 1) "bjz"
   2) "2.6361"
2) 1) "bjn"
   2) "5.1452"
3) 1) "bjx"
   2) "6.6723"
  1. 计算北京西的坐标与hash值
127.0.0.1:6379> GEOPOS g1 bjz
1) 1) "116.42802804708480835"
   2) "39.90373880538094653"
127.0.0.1:6379> GEOHASH g1 bjz
1) "wx4g12k21s0"

三、实战搜索附近商铺

1、接口名称

Redis GEO功能详细介绍与实战

2、商家列表展示距离

当我们点击美食之后,会出现一系列的商家,商家中可以按照多种排序方式,我们此时关注的是距离,这个地方就需要使用到我们的GEO,向后台传入当前app收集的地址(我们此处是写死的) ,以当前坐标作为圆心,同时绑定相同的店家类型type,以及分页信息,把这几个条件传入后台,后台查询出对应的数据再返回。
如图:
Redis GEO功能详细介绍与实战

3、约定数据存储规则

Redis GEO功能详细介绍与实战
我们要做的事情是:将数据库表中的数据导入到redis中去,redis中的GEO,GEO在redis中就一个menber和一个经纬度,我们把x和y轴传入到redis做的经纬度位置去,但我们不能把所有的数据都放入到menber中去,毕竟作为redis是一个内存级数据库,如果存海量数据,redis还是力不从心,所以我们在这个地方存储他的id即可。

但是这个时候还有一个问题,就是在redis中并没有存储type,所以我们无法根据type来对数据进行筛选,所以我们可以按照商户类型做分组,类型相同的商户作为同一组,以typeId为key存入同一个GEO集合中即可

  • 测试:
void loadShopData() {
    // 1.查询店铺信息
    List<Shop> list = shopService.list();
    // 2.把店铺分组,按照typeId分组,typeId一致的放到一个集合
    Map<Long, List<Shop>> map = list.stream().collect(Collectors.groupingBy(Shop::getTypeId));
    // 3.分批完成写入Redis
    for (Map.Entry<Long, List<Shop>> entry : map.entrySet()) {
        // 3.1.获取类型id
        Long typeId = entry.getKey();
        String key = SHOP_GEO_KEY + typeId;
        // 3.2.获取同类型的店铺的集合
        List<Shop> value = entry.getValue();
        List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>(value.size());
        // 3.3.写入redis GEOADD key 经度 纬度 member
        for (Shop shop : value) {
            // stringRedisTemplate.opsForGeo().add(key, new Point(shop.getX(), shop.getY()), shop.getId().toString());
            locations.add(new RedisGeoCommands.GeoLocation<>(
                    shop.getId().toString(),
                    new Point(shop.getX(), shop.getY())
            ));
        }
        stringRedisTemplate.opsForGeo().add(key, locations);
    }
}
  • 结果:
    Redis GEO功能详细介绍与实战

4、实现附近商户功能

4.1 第一步:导入pom
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <artifactId>spring-data-redis</artifactId>
            <groupId>org.springframework.data</groupId>
        </exclusion>
        <exclusion>
            <artifactId>lettuce-core</artifactId>
            <groupId>io.lettuce</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.6.2</version>
</dependency>
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>6.1.6.RELEASE</version>
</dependency>
4.2 第二步:写接口ShopController

传入参数:

  • typeId:商品类型id
  • current: 当前页码
  • x : 经度
  • y : 纬度
@GetMapping("/of/type")
public Result queryShopByType(
        @RequestParam("typeId") Integer typeId,
        @RequestParam(value = "current", defaultValue = "1") Integer current,
        @RequestParam(value = "x", required = false) Double x,
        @RequestParam(value = "y", required = false) Double y
) {
   return shopService.queryShopByType(typeId, current, x, y);
}
4.3 第三步:实现
  1. 判断是否需要根据坐标查询
  2. 计算分页参数
  3. 查询redis、按照距离排序、分页。结果:shopId、distance
  4. 解析出id
  5. 根据id查询Shop
  6. 返回店铺数据
@Override
    public Result queryShopByType(Integer typeId, Integer current, Double x, Double y) {
        // 1.判断是否需要根据坐标查询
        if (x == null || y == null) {
            // 不需要坐标查询,按数据库查询
            Page<Shop> page = query()
                    .eq("type_id", typeId)
                    .page(new Page<>(current, SystemConstants.DEFAULT_PAGE_SIZE));
            // 返回数据
            return Result.ok(page.getRecords());
        }

        // 2.计算分页参数
        int from = (current - 1) * SystemConstants.DEFAULT_PAGE_SIZE;
        int end = current * SystemConstants.DEFAULT_PAGE_SIZE;

        // 3.查询redis、按照距离排序、分页。结果:shopId、distance
        String key = SHOP_GEO_KEY + typeId;
        GeoResults<RedisGeoCommands.GeoLocation<String>> results = stringRedisTemplate.opsForGeo() // GEOSEARCH key BYLONLAT x y BYRADIUS 10 WITHDISTANCE
                .search(
                        key,
                        GeoReference.fromCoordinate(x, y),
                        new Distance(5000),
                        RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs().includeDistance().limit(end)
                );
        // 4.解析出id
        if (results == null) {
            return Result.ok(Collections.emptyList());
        }
        List<GeoResult<RedisGeoCommands.GeoLocation<String>>> list = results.getContent();
        if (list.size() <= from) {
            // 没有下一页了,结束
            return Result.ok(Collections.emptyList());
        }
        // 4.1.截取 from ~ end的部分
        List<Long> ids = new ArrayList<>(list.size());
        Map<String, Distance> distanceMap = new HashMap<>(list.size());
        list.stream().skip(from).forEach(result -> {
            // 4.2.获取店铺id
            String shopIdStr = result.getContent().getName();
            ids.add(Long.valueOf(shopIdStr));
            // 4.3.获取距离
            Distance distance = result.getDistance();
            distanceMap.put(shopIdStr, distance);
        });
        // 5.根据id查询Shop
        String idStr = StrUtil.join(",", ids);
        List<Shop> shops = query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();
        for (Shop shop : shops) {
            shop.setDistance(distanceMap.get(shop.getId().toString()).getValue());
        }
        // 6.返回
        return Result.ok(shops);
    }

四、源码下载

https://gitee.com/charlinchenlin/koo-erp文章来源地址https://www.toymoban.com/news/detail-470177.html

到了这里,关于Redis GEO功能详细介绍与实战的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • API低代码平台介绍1-功能概述

      ADI平台是指Application data integration,即“应用数据集成”,使用springboot开发,并通过springcloud实现微服务,是一个动态定义Http API接口的“零代码”或“低代码”平台,支持GET(查)、POST(增)、PUT(改)、DELETE(删)四种请求方式直接操作数据库数据;可动态添加多个数据源(实现原

    2024年02月06日
    浏览(62)
  • Redis Geo:掌握地理空间数据的艺术

    欢迎来到我的博客,代码的世界里,每一行都是一个故事 在移动互联网和物联网的时代,地理位置数据无处不在。从导航和配送到社交网络和广告,地理位置信息正在重新定义我们与世界的互动方式。但是,处理和分析这些大量的地理空间数据绝非易事。这时,Redis Geo应运而

    2024年02月02日
    浏览(41)
  • 【Redis】特殊数据类型 Geo (地理位置)

    除了五中基本的数据类型外,Redis还支持两种特殊的数据类型,第一种 Geo (地理位置):用于存储地理位置相关的数据,例如经纬度、距离等。第二种 Stream (流):是一个高级的列表类型,支持对列表的批量操作,如添加多个元素、获取多个元素等。 Redis GEO(Geo Redis)是一个用

    2024年02月15日
    浏览(38)
  • Redis GEO地理位置信息的应用

    Redis的GEO操作是一种基于地理位置信息进行操作的功能。它使用经度和纬度坐标来表示地理位置,支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能。 1.GEOADD添加位置信息 将一个或多个指定的地理位置(经度、纬度、名称)添加到指定的键

    2024年02月08日
    浏览(51)
  • BurpSuite超详细安装教程-功能概述-配置-使用教程---(附下载链接)

    BurpSuite是渗透测试、漏洞挖掘以及Web应用程序测试的最佳工具之一,是一款用于攻击web 应用程序的集成攻击测试平台,可以进行抓包、重放、爆破,包含许多工具,能处理对应的HTTP消息、持久性、认证、代理、日志、警报。 链接: 百度网盘链接 提取码:ranz 下载后解压 如

    2024年02月03日
    浏览(45)
  • 【Redis】GEO数据类型之附近的店铺实现

    目录 一、GEO 1、概念 2、相关命令 1.GEOADD 2.GEODIST 3.GEOHASH 4.GEOPOS 5.GEORADIUS 6.GEOSEARCH 7.GEOSEARCHSTORE 二、附近的店铺 1、实现思路 2、代码实现 GEO全称Geolocation,Redis种的一种数据结构他代表地理坐标 1.GEOADD 向redis中添加一个地理空间信息,其中包含经度、维度、值(member) 2.GEODI

    2024年02月07日
    浏览(41)
  • GEO数据挖掘(一)基础介绍

    生信技能树学徒学习第二周 一、GEO数据库简介        GEO全称Gene Expression Omnibus data base,由美国国立生物技术信息中心NCBI创建并维护的基因表达数据库(通过NCBI首页,All Databases下拉框中选择GEO DataSets)。收录了世界各国研究机构提交的高通量基因表达数据。2000年开始建立的时

    2024年02月13日
    浏览(37)
  • Redis GEO 类型与 API 结合,地理位置优化的绝佳实践

    🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者 📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代 🌲文章所在专栏:MySQL、Redis、业务设计 🤔 我当前正在学习微服务领域、云原生领域、消息中间件等架构、原理知识 💬 向我

    2024年02月08日
    浏览(35)
  • 【微信小程序 | 实战开发】ES5、ES6概述和新特性介绍

    个人名片: 🐼 作者简介:一名大二在校生,喜欢编程🎋 🐻‍❄️ 个人主页🥇: 小新爱学习. 🐼 个人WeChat:hmmwx53 🕊️ 系列专栏:🖼️ 零基础学Java——小白入门必备 重识C语言——复习回顾

    2024年02月09日
    浏览(40)
  • 【Redis】Redis是什么、能干什么、主要功能和工作原理的详细讲解

    🚀欢迎来到本文🚀 🍉个人简介:陈童学哦,目前学习C/C++、算法、Python、Java等方向,一个正在慢慢前行的普通人。 🏀系列专栏:陈童学的日记 💡其他专栏:C++STL,感兴趣的小伙伴可以看看。 🎁希望各位→点赞👍 + 收藏⭐️ + 留言📝 ​ ⛱️万物从心起,心动则万物动🏄

    2024年02月11日
    浏览(35)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包