Redis中GEO数据结构实现附近商户搜索

news2024/11/25 12:55:23

Redis的版本必须是6.2以上

在测试类中将数据导入Redis

@Test
    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:" + 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);
            }
        }
    }

控制层代码

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

服务层代码

@Override
    public Result queryShopByType(Integer typeId, Integer current, Double x, Double y) {
        //判断是否需要根据坐标进行查询
        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());
        }
        //计算分页参数
        int from = (current - 1) * SystemConstants.DEFAULT_PAGE_SIZE;
        int end = current * SystemConstants.DEFAULT_PAGE_SIZE;

        //查询Redis,按照距离排序、分页。结果:shopId、distance  ,通过limit获取的是0-end,之后进行截取
        String key = SHOP_GEO_KEY + typeId;
        GeoResults<RedisGeoCommands.GeoLocation<String>> results = stringRedisTemplate.opsForGeo().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 ->{
            //获取店铺id
            String shopIdStr = result.getContent().getName();
            ids.add(Long.parseLong(shopIdStr));
            //获取距离
            Distance distance = result.getDistance();
            distanceMap.put(shopIdStr, distance);
        });
        //根据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.getImages().toString()).getValue());
        }
        return Result.ok(shops);
    }

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

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

相关文章

Spring Boot 三层架构开发模式入门

在 Spring Boot 项目中&#xff0c;构建清晰、易于维护的代码结构至关重要。传统业务逻辑方式往往将所有代码混杂在一起&#xff0c;导致代码难以理解、修改和扩展。三层架构模式的出现正是为了解决这些问题&#xff0c;让我们深入了解它带来的改变。 一、传统业务逻辑方式 假…

实战六:使用嵌套循环输出九九乘法表,总结了五种方法

问题描述: 使用嵌套循环输出九九乘法表&#xff0c;内层循环与外层循环的关系&#xff0c;输出的数据的个数与行数相同&#xff0c;即第一行输出一个&#xff0c;111&#xff0c;第二行输出两个122 2*24依次类推。 编程&#xff1a; 1.方法一&#xff1a; for i in range(1…

昊辰创投注资众见科技,共筑智能眼镜未来:新一轮融资加速技术创新与市场扩张

众见科技:智能眼镜领域的新星,昊辰创投助力新轮融资 在智能眼镜市场日益成为科技创新与资本追逐焦点的今天,深圳众见科技有限公司(以下简称“众见科技”)以其卓越的技术实力和前瞻性的市场布局,成功吸引了昊辰创投的青睐,完成了新一轮融资。此次融资不仅标志着众见科技在…

基于SpringBoot+Vue的高校运动会管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

华为OD机试 - 转骰子(Java 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

AIGC实践|AI助力文旅短视频创作全流程

前言&#xff1a; 受到央视《AI我中华》及各地文旅AI宣传片的启发&#xff0c;本次我将尝试使用AI辅助进行城市宣传片的创作探索。我将尽可能详细的展示使用AI辅助创作城市宣传片的全过程&#xff0c;从灵感捕捉到最终成品呈现。现在&#xff0c;让我们一同踏上这段充满创意的探…

中国剩余定理专题

按照m之间的性质来决定采用什么方法 是否互质&#xff1f; 互质——中国剩余定理 不互质——拓展欧几里得 拓展中国剩余定理 互质情况下&#xff0c;是否均为质数&#xff1f; 是—— 费马小定理求逆元 否——拓展欧几里得求逆元 互质条件下的拓展欧几里得中国剩余定理 题…

Spring Boot框架:新闻推荐系统开发新趋势

3系统分析 3.1可行性分析 通过对本新闻推荐系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本新闻推荐系统采用JAVA作为开发语言&#xff0c;Spring Boot框…

序列化与反序列化基础及反序列化漏洞(附案例)

参考文章&#xff1a; [web安全原理]PHP反序列化漏洞 - 笑花大王 - 博客园 (cnblogs.com) 一、概念 为了能有效的存储数据而不丢失数据的类型和内容&#xff0c;经常需要通过序列化对数据进行处理&#xff0c;将数据进行序列化后&#xff0c;会生成一个字符串&#xff0c;字符…

冯诺依曼体系结构与操作系统简介

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 冯诺依曼体系结构与操作系统简介 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1.…

CSP-J Day 5 模拟赛补题报告

姓名&#xff1a;王胤皓&#xff0c;校区&#xff1a;和谐校区&#xff0c;考试时间&#xff1a; 2024 2024 2024 年 10 10 10 月 5 5 5 日 9 : 00 : 00 9:00:00 9:00:00~ 12 : 30 : 00 12:30:00 12:30:00&#xff0c;学号&#xff1a; S 07738 S07738 S07738 请关注作者的…

分治算法(1)_颜色分类

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 分治算法(1)_颜色分类 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. 分治思…

PostgreSQL 任意命令执行漏洞(CVE-2019-9193)

记一次授权攻击通过PostgreSql弱口令拿到服务器权限的事件。 使用靶机复现攻击过程。 过程 在信息收集过程中&#xff0c;获取到在公网服务器上开启了5432端口&#xff0c;尝试进行暴破&#xff0c;获取到数据库名为默认postgres&#xff0c;密码为1 随后连接进PostgreSql …

(杨辉三角) 攻防世界--->notsequence

学习笔记。(不想看可以直接跳正文。) 前言&#xff1a;仿佛又回到高中 - - 只不过&#xff0c;是以另一种形式再次出现。 学习思维为主&#xff0c;做题位次。&#xff08;后面再补。&#xff09; 前置知识&#xff1a; 什么是杨辉三角&#xff1a; 杨辉三角_百度百科 (bai…

【CSS in Depth 2 精译_045】7.1 CSS 响应式设计中的移动端优先设计原则(上)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…

MySQL【知识改变命运】02

数据类型 1&#xff1a;数据值类型2&#xff1a;字符串类型/二进制类型3&#xff1a;⽇期类型 前言&#xff1a;数据类型一共分为四类&#xff1a;数据值类型&#xff0c;字符串类型&#xff0c;二进制类型&#xff0c;日期类型。 1&#xff1a;数据值类型 类型大小说明BIT[(M…

Spring Boot 集成 Flowable UI 实现请假流程 Demo

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 在现代企业应用中&#xff0c;工作流管理是一个至关重要的部分。通过使用Spring Boot和Flowable&#xff0c;可以方便地构建和管理工作流。本文将详细介绍如何在Spring Boot项目中集成Flowable UI&#xff0c…

【Java】—— 泛型:泛型的理解及其在集合(List,Set)、比较器(Comparator)中的使用

目录 1. 泛型概述 1.1 生活中的例子 1.2 泛型的引入 2. 使用泛型举例 2.1 集合中使用泛型 2.1.1 举例 2.1.2 练习 2.2 比较器中使用泛型 2.2.1 举例 2.2.2 练习 1. 泛型概述 1.1 生活中的例子 举例1&#xff1a;中药店&#xff0c;每个抽屉外面贴着标签 举例2&…

Chromium 添加书签功能浅析c++

1、在点击添加书签时候此UI控制逻辑代码在 chrome\browser\ui\views\bookmarks\bookmark_bar_view.cc chrome\browser\ui\views\bookmarks\bookmark_bar_view.h 可以在此看到完成 移除 按钮逻辑&#xff0c;以及书签监听事件等。。。 // Implementation for BookmarkNodeAdd…

FastAdmin Apache下设置伪静态

FastAdmin Apache下设置伪静态 一、引言 FastAdmin 是一个基于ThinkPHP和Bootstrap框架开发的快速后台开发框架&#xff0c;它以其简洁、高效、易于扩展的特点&#xff0c;广受开发者的喜爱。在部署FastAdmin项目时&#xff0c;为了提高访问速度和用户体验&#xff0c;我们通…