(黑马点评)七、附近商户系列功能实现

 7.1 GEO数据结构的认识及其基本使用演示

7.1.1 GEO的介绍

GEO,代表地理坐标Redis3.2版本中加入了对GEO的支持,允许存储地理坐标信息,帮助我们根据经纬度来检索数据。常见的命令有:

 GEOADD:添加一个地理空间信息,包含:经度(longitude)、纬度(latitude)、值(member

 GEODIST:计算指定的两个点之间的距离并返回

GEOHASH:将指定member的坐标转为hash字符串形式并返回

GEOPOS:返回指定member的坐标

GEORADIUS:指定圆心、半径,找到该圆内包含的所有member,并按照与圆心之间的距离排序后返回。6.2以后已废弃

GEOSEARCH:在指定范围内搜索member,并按照与指定点之间的距离排序后返回。范围可以是圆形或矩形。6.2.新功能

GEOSEARCHSTORE:与GEOSEARCH功能一致,不过可以把结果存储到一个指定的key 6.2.新功能

7.1.2 GEO的基本使用演示

通过 GEOADD  group x y member 添加经纬坐标

以下是通过ADD命令添加的三条数据:


北京南站( 116.378248 39.865275 )
北京站( 116.42803 39.903738 )
北京西站( 116.322287 39.893729 )

通过GEODIST group a地 b地 单位,计算两点间直线距离 

以下,分别计算北京南到北京西、北京站到北京西的距离

通过GEOSEARCH ,计算附近xx距离的所有点的信息

以下是搜索天安门附近10km火车站

7.2 附近商户搜索功能的实现

7.2.1 需求分析及接口说明

        这个需求需要使用GEO数据结构去统计以当前登录用户的地理位置为中心,向外扩散一段距离的店铺信息。同时,为了更好的对商店信息进行管理,我们需要先将店铺信息按类型存储到Redis中。

 

7.2.2 功能实现说明

1. 编写测试类,提前将店铺坐标信息存入Redis中
@Testvoid LoadShopData(){//1. 查询店铺信息List<Shop> list = shopService.list();//2. 把店铺按照typeId分组Map<Long,List<Shop>> shopMap = list.stream().collect(Collectors.groupingBy(shop -> shop.getTypeId()));//3. 分批写入redisfor(Map.Entry<Long,List<Shop>> entry : shopMap.entrySet()) {//3.1 获取类型idLong typeId = entry.getKey();String key = RedisConstants.SHOP_GEO_KEY + typeId;//3.2 获取同类型的店铺列表List<Shop> shops = entry.getValue();// Redis 将 name 和 Point 封装在一起的一种用法List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>();//3.3 写入Redis GEOADD key x y memberfor(Shop shop : shops){
//                stringRedisTemplate.opsForGeo().add(key,new Point(shop.getX(),shop.getY()),shop.getId().toString());// 先把所有的点存好,再一次性存入Redis,性能更好locations.add(new RedisGeoCommands.GeoLocation<>(shop.getId().toString(),new Point(shop.getX(),shop.getY())));}stringRedisTemplate.opsForGeo().add(key, locations);}}

分类存放:

2. 更换依赖版本

原先的依赖没办法使用GEO的最新语法,我们需要在配置文件中进行版本更替

            <!--排除旧版本--><exclusions><exclusion><artifactId>lettuce-core</artifactId><groupId>io.lettuce</groupId></exclusion><exclusion><artifactId>spring-data-redis</artifactId><groupId>org.springframework.data</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>

【推荐插件】Maven helper

用它可以更加方便的进行包管理

3. 修改queryShopByType接口,实现分类分页查询功能

需要传入的参数变成四个

/*** 根据商铺类型分页查询商铺信息* @param typeId 商铺类型* @param current 页码* @return 商铺列表*/@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);}

实现类中:

【步骤说明】

1. 根据传参判断本次查询任务需不需要坐标,如果不需要,那就直接按照标准分页查询去做

2. 需要查坐标,则计算分页参数:

        包括: 起始值 from = (current - 1) * SystemConstants.DEFAULT_PAGE_SIZE;

                    终点值 end = current * SystemConstants.DEFAULT_PAGE_SIZE;

3. 在Redis中使用查询店铺地址信息

opsForGeo().search(...RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs().includeDistance().limit(end)) 

4. 使用getContent()方法解析出店铺信息、距离信息

5. 使用stream流截取from 到 end 部分的数据进行遍历

6. 获取店铺id、距离信息分装成一一对应的Map集合

7. 通过ids集合,查询店铺信息集合

8. 通过Map集合,匹配店铺信息结合与距离信息

9. 返回结果

      

/*** 根据类型分页分类查询店铺信息* @param typeId* @param current* @param x* @param y* @return*/@Overridepublic 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 、 distanceString key = SHOP_GEO_KEY + typeId;GeoResults<RedisGeoCommands.GeoLocation<String>> results = stringRedisTemplate.opsForGeo().search(key,GeoReference.fromCoordinate(x,y),new Distance(Shop_FEO_DISTANCE),RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs().includeDistance().limit(end));//4. 解析出idif(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.subList(from,end);// 定义一个集合,保存店铺id和距离的关系List<Long> ids = new ArrayList<>(list.size());Map<String,Distance> distanceMap = new HashMap<>(list.size());list.stream().skip(from).forEach(result -> {// 4.2 获取店铺idString shopIdStr = result.getContent().getName();ids.add(Long.valueOf(shopIdStr));// 4.3 获取距离Distance distance = result.getDistance();distanceMap.put(shopIdStr,distance);});//5. 查询店铺List<Shop> shops = query().in("id",ids).last("ORDER BY FIELD(id," + StrUtil.join(",",ids) + ")").list();// 匹配店铺距离for(Shop shop : shops) {shop.setDistance(distanceMap.get(shop.getId().toString()).getValue());}//6. 返回结果return Result.ok(shops);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144026.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Java创建教程!(*  ̄3)(ε ̄ *)

Java 构造函数 Java面向对象设计 - Java构造函数 构造函数是用于在对象创建后立即初始化对象的代码块。 构造函数的结构看起来类似于一个方法。 声明构造函数 构造函数声明的一般语法是 <Modifiers> <Constructor Name>(<parameters list>) throws <…

【Binlog实战】:基于Spring监听Binlog日志

【Binlog实战】&#xff1a;基于Spring监听Binlog日志 binlog的三种模式 MySQL 的二进制日志&#xff08;binlog&#xff09;有三种不同的格式&#xff0c;通常被称为 binlog 模式。这三种模式分别是 Statement 模式、Row 模式和Mixed 模式。 Statement 模式&#xff1a; 在 …

JavaWEB概述

JavaWEB概述 一、什么是JavaWEB 用Java技术解决web互联网领域的技术栈。要学习JavaWEB首先得知道什么是客户端和服务端 客户端&#xff1a;简而言之&#xff0c;这就是使用方&#xff0c;比如我们下载一个软件去使用&#xff0c;里面有很多我们可以使用的功能&#xff0c;那…

Flutter问题记录 - 适配Xcode 16和iOS 18

文章目录 前言开发环境问题及解决方案1. Upload Symbols Failed2. type UIApplication does not conform to protocol Launcher3. method does not override any method from its superclass 最后 前言 为了新的镜像功能升级了macOS 15和iOS 18&#xff0c;Xcode也不可避免的需…

传输层协议——udp/tcp

目录 再谈端口号 udp 协议 理解报头 udp特点 缓冲区 udp使用的注意事项 tcp协议 TCP的可靠性与提高效率的策略 序号/确认序号 窗口大小 ACK&#xff1a; PSH URG RST 保活机制 重传 三次握手(SYN) 四次挥手(FIN) 流量控制 滑动窗口 拥塞控制 延迟应答 捎带应答 面…

面向切面:单元测试、事务、资源操作

目录 一、单元测试二、事务2.1、概述2.1.1、编程式事务2.1.2、声明式事务 2.2、JdbcTemplate2.3、基于注解的声明式事务2.3.1、基本用例-实现注解式的声明事务2.3.2、事务属性&#xff1a;只读2.3.3、事务属性&#xff1a;超时2.3.4、事务属性&#xff1a;回滚策略2.3.5、事务属…

八戒农场小程序V2最新源码

一.介绍 八戒农场V2小程序源码&#xff0c;前端工具上传&#xff0c;包更新、这个是源码&#xff0c;覆盖即可升级版&#xff08;修复很多问题&#xff09;&#xff1b;

基于UKF(无迹卡尔曼滤波)的SINS/GPS集成导航仿真程序【需要PSINS工具箱支持】

文章目录 主要特点内容包括运行截图 基于UKF&#xff08;无迹卡尔曼滤波&#xff09;的SINS/GPS集成导航仿真程序&#xff08;需要基于PSINS工具箱&#xff0c;工具箱是开源的&#xff0c;如果需要&#xff0c;可以确认收货后找我要链接&#xff09;。该程序能够高效地模拟导航…

Python VS Golng 谁更胜一筹?

今天我们聊聊Python和Golang这俩到底谁更胜一筹。 这个话题我已经在各种技术论坛上看到无数次了&#xff0c;每次都能引起一波热烈的讨论。作为一个多年写代码的老程序员&#xff0c;今天就站在我的角度&#xff0c;和大家掰扯掰扯这两个语言各自的优缺点。 1. 性能与并发模型…

软件测试技术之 GPU 单元测试是什么!

1 背景 测试是开发的一个非常重要的方面&#xff0c;可以在很大程度上决定一个应用程序的命运。良好的测试可以在早期捕获导致应用程序崩溃的问题&#xff0c;但较差的测试往往总是导致故障和停机。 单元测试用于测试各个代码组件&#xff0c;并确保代码按照预期的方式工作。单…

力扣(LeetCode)每日一题 1184. 公交站间的距离

题目链接https://leetcode.cn/problems/distance-between-bus-stops/description/?envTypedaily-question&envId2024-09-16 环形公交路线上有 n 个站&#xff0c;按次序从 0 到 n - 1 进行编号。我们已知每一对相邻公交站之间的距离&#xff0c;distance[i] 表示编号为 i …

C语言--结构体(学习笔记)

内容借鉴于b站杜远超官方频道&#xff08;C语言结构体详解【干货】&#xff09; 首先C语言中定义变量格式为“数据类型 变量名”&#xff0c;如int a; float b;等等。 那么结构体则是将多个变量&#xff08;数据类型 变量名&#xff09;结合在一起的一种新的数据类型&…

Elasticsearch 下载安装及使用总结

官网文档地址&#xff1a;Elasticsearch Guide [8.13] 官网下载地址&#xff1a;Download Elasticsearch 1. 下载安装 1、下载对应系统的版本 这里下载的 Elasticsearch 版本为 8.13.2&#xff0c;Elasticsearch 依赖 Java&#xff0c;因此要先在服务器上安装 JDK&#xff…

ARM 工业边缘计算机与 C# 编程的完美融合

在工业领域&#xff0c;随着智能化和数字化的不断推进&#xff0c;ARM 工业边缘计算机凭借其出色的性能和低功耗等优势&#xff0c;逐渐成为众多应用场景的重要支撑。而 C# 编程语言的强大功能和广泛适用性&#xff0c;使其在与 ARM 工业边缘计算机的结合中展现出了巨大的潜力。…

Spring考点总结

01.Spring框架的基本理解 关键字:核心思想IOC\AOP\作用(解耦、简化)&#xff0c;简单描述框架组成 Spring框架是一款轻量级的开发框架&#xff0c;核心思想是IOC&#xff08;控制反转&#xff09;和AOP&#xff08;面向切面编程&#xff09;&#xff0c; 为Java应用程序开发…

武器检测系统源码分享

武器检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

Python基础(八)——MySql数据库

一.数据库 【库——>表——>数据】 借助数据库对数据进行组织存储&#xff0c;借助SQL语言对数据库、数据进行操作管理 Mysql数据库 下载&#xff1a;https://www.mysql.com/ 查看是否安装配置成功&#xff1a; 安装DBeaver用于Mysql数据库图形化 安装&#xff1a;…

分布式光伏充换电站相关建议

了推动光伏发电和电动汽车的发展&#xff0c;在土地资源日益紧缺的城市区域&#xff0c;需合理共享现有土地资源&#xff0c;实现资源大化利用。城市变电站由于其合理的分布密度以及便利的接入条件&#xff0c;对于建设分布式光伏发电、充换电站具有很好的优势。可利用变电站旧…

统信服务器操作系统【1050e版】安装手册

统信服务器操作系统1050e版本的安装 文章目录 功能概述一、准备环境二、安装方式介绍安装步骤步骤一:制作启动盘步骤二:系统的安装步骤三:安装引导界面步骤四:图形化界面安装步骤五:选择安装引导程序语言步骤六:进入安装界面步骤七:设置键盘步骤八:设置系统语言步骤九:…

关于wordPress中的用户登录注册等问题

前言 大家在做类似的功能的时候&#xff0c;有没有相关的疑问。那就是我都已经选择好了相应的主题和模版&#xff0c;但是为什么都没有用户注册和用户登录的页面存在呢&#xff1f; WordPress默认情况下不提供用户注册和登录功能的原因是它最初是作为一个博客平台开发的&…