分享一个 SpringBoot + Redis 实现「查找附近的人」的小技巧
前言
SpringDataRedis提供了十分简单的地理位置定位的功能,今天我就用一小段代码告诉大家如何实现。
正文
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、更新用户位置信息
编写一个更新用户位置信息的接口,其中几个参数的含义如下:
userId:要更新位置信息或查询附近的人的用户ID。longitude:新的经度值或查询附近的人时指定的中心经度。latitude:新的纬度值或查询附近的人时指定的中心纬度。
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 更新用户位置信息
@PostMapping("/{userId}/location")
public void updateUserLocation(@PathVariable long userId,
@RequestParam double longitude,
@RequestParam double latitude) {
String userLocationKey = "user_location";
// 使用Redis的地理位置操作对象,将用户的经纬度信息添加到指定的key中
redisTemplate.opsForGeo().add(userLocationKey,
new Point(longitude, latitude), userId);
}
3、获取附近的人
编写一个获取附近的人的接口
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 获取附近的人
@GetMapping("/{userId}/nearby")
public List<Object> getNearbyUsers(@PathVariable long userId,
@RequestParam double longitude,
@RequestParam double latitude,
@RequestParam double radius) {
String userLocationKey = "user_location";
Distance distance = new Distance(radius, Metrics.KILOMETERS);
Circle circle = new Circle(new Point(longitude, latitude), distance);
// 使用Redis的地理位置操作对象,在指定范围内查询附近的用户位置信息
GeoResults<GeoLocation<Object>> geoResults = redisTemplate
.opsForGeo()
.radius(userLocationKey, circle);
List<Object> nearbyUsers = new ArrayList<>();
for (GeoResult<GeoLocation<Object>> geoResult : geoResults.getContent()) {
Object memberId = geoResult.getContent().getName();
// 排除查询用户本身
if (!memberId.equals(userId)) {
nearbyUsers.add(memberId);
}
}
return nearbyUsers;
}
其中几个重要属性的含义如下:
Distance:Spring Data Redis中的一个类,用于表示距离。它可以用于指定搜索半径或者计算两点之间的距离。在示例代码中,我们创建了一个Distance对象来指定搜索范围的半径,并使用Metrics.KILOMETERS表示以千米为单位的距离。
Circle:Spring Data Redis中的一个类,用于表示圆形区域。它由一个中心点(用Point表示)和一个半径(用Distance表示)组成。在示例代码中,我们通过传入中心点和距离创建了一个Circle对象,用于定义附近人搜索的圆形区域。
GeoResults:Spring Data Redis中的一个类,用于表示地理位置查询的结果。它包含了一个Content属性,该属性是一个List<GeoResult<GeoLocation<Object>>>类型的列表,其中每个GeoResult对象都包含了地理位置信息以及与该位置相关的其他数据。在示例代码中,我们通过调用redisTemplate.opsForGeo().radius()方法返回了一个GeoResults对象,其中包含了在指定范围内的所有地理位置结果。
4、完整代码如下
为了用更少的代码片段让大家一目了然,所以都写在controller中,应用在项目里面时最好把其中的实现部分都转移到service中。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 更新用户位置信息
@PostMapping("/{userId}/location")
public void updateUserLocation(@PathVariable long userId,
@RequestParam double longitude,
@RequestParam double latitude) {
String userLocationKey = "user_location";
// 使用Redis的地理位置操作对象,将用户的经纬度信息添加到指定的key中
redisTemplate.opsForGeo().add(userLocationKey,
new Point(longitude, latitude), userId);
}
// 获取附近的人
@GetMapping("/{userId}/nearby")
public List<Object> getNearbyUsers(@PathVariable long userId,
@RequestParam double longitude,
@RequestParam double latitude,
@RequestParam double radius) {
String userLocationKey = "user_location";
Distance distance = new Distance(radius, Metrics.KILOMETERS);
Circle circle = new Circle(new Point(longitude, latitude), distance);
// 使用Redis的地理位置操作对象,在指定范围内查询附近的用户位置信息
GeoResults<GeoLocation<Object>> geoResults = redisTemplate
.opsForGeo()
.radius(userLocationKey, circle);
List<Object> nearbyUsers = new ArrayList<>();
for (GeoResult<GeoLocation<Object>> geoResult : geoResults.getContent()) {
Object memberId = geoResult.getContent().getName();
// 排除查询用户本身
if (!memberId.equals(userId)) {
nearbyUsers.add(memberId);
}
}
return nearbyUsers;
}
}
总结
SpringDataRedis本身也是对Redis底层命令的封装,所以Jedis里面其实也提供了差不多的实现,大家可以自己去试一试。
如果有redis相关的面试,如果能说出Redis的Geo命令,面试官就知道你有研究过,是可以大大加分的。
侧面证明了你对Redis的了解不局限于简单的set、get命令,希望这篇文章对大家有所帮助。
如果喜欢,记得点赞关注↓↓↓,持续分享干货!
分享一个 SpringBoot + Redis 实现「查找附近的人」的小技巧的更多相关文章
- 分享一个springboot脚手架
项目介绍 在我们开发项目的时候各个项目之间总有一些可共用的代码或者配置,如果我们每新建一个项目就把代码复制粘贴再修改就显得很没有必要.于是我就做了一个 poseidon-boot-starter 该项 ...
- Redis(6)——GeoHash查找附近的人
像微信 "附近的人",美团 "附近的餐厅",支付宝共享单车 "附近的车" 是怎么设计实现的呢? 一.使用数据库实现查找附近的人 我们都知道, ...
- 一个操作轻松截取长图,Win10上网截长图小技巧!
截屏的方法有很多,但是有时候我们会遇到比电脑屏幕还大的图,比如网站上的长图.N条引用的评论...你要怎么截取呢?是不是最多只能截全屏?还是要做到第三方的截图软件呢? 下面介绍一种win10电脑自带的滚 ...
- 分享一个批量修改文件编码的python脚本
分享一个自己编写的递归查找子目录,将所有cpp文件编码修改为utf-8编码格式的小脚本 #i!/usr/bin/env python3 # -*- coding:utf-8 -*- import os ...
- 使用k8s部署springboot+redis简单应用
准备 本文将使用k8s部署一个springboot+redis应用,由于是示例,所以功能比较简单,只有设置值和获取值两个api. (1)设置值 (2)获取值 构建Web应用 (1)创建一个spring ...
- Redis 是怎么实现 “附近的人” 的?
针对"附近的人"这一位置服务领域的应用场景,常见的可使用PG.MySQL和MongoDB等多种DB的空间索引进行实现. 而Redis另辟蹊径,结合其有序队列zset以及geohas ...
- 补习系列(14)-springboot redis 整合-数据读写
目录 一.简介 二.SpringBoot Redis 读写 A. 引入 spring-data-redis B. 序列化 C. 读写样例 三.方法级缓存 四.连接池 小结 一.简介 在 补习系列(A3 ...
- springboot学习笔记:2.搭建你的第一个springboot应用
1.开发环境 (推荐):jdk1.8+Maven(3.2+)+Intellij IDEA+windows10; 说明: jdk:springboot官方说的很明确,到目前版本的springboot(1 ...
- Git.Framework 框架随手记-- 分享一个"比较垃圾"的项目
本文主要分享一个Git.Framework 开发的一个项目的部分源码,此项目代码"比较垃圾",所以请各位码农,码畜,码神,码圣勿喷!发此文只为记录工作问题以及分享问题! 一. 项目 ...
- springboot redis多数据源
springboot中默认的redis配置是只能对单个redis库进行操作的. 那么我们需要多个库操作的时候这个时候就可以采用redis多数据源. 本代码参考RedisAutoConfiguratio ...
随机推荐
- Spark常用算子
Spark是一个快速.通用.可扩展的分布式数据处理引擎,支持各种数据处理任务.Spark提供了许多强大的算子,用于对数据集进行各种转换和操作. 以下是Spark中常用的一些算子: 1. map:对RD ...
- 如何通过CAD图中的坐标来确定是哪个坐标系
国内常见的坐标系 坐标系分为以下两种: 地理坐标系(Geographic Coordinate System, GCS) 投影坐标系(Projected Coordinate System, PCS) ...
- 腾讯云 cloudbase 云开发使用笔记
产品概述 云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为开发者提供高可用.自动弹性扩缩的后端云服务,包含计算.存储.托管等 serverless ...
- K8S | 核心原理分析
目录 一.背景 二.持续集成 三.K8S架构 1.核心组件 2.分层结构 3.核心能力 3.1 发现与负载 3.2 调度 3.3 自动伸缩 四.应用案例 1.服务部署 2.交互流程 五.参考源码 整体 ...
- c# 如何将枚举以下拉数据源的形式返回给前端
前言: 相信各位有碰到过与我类似的问题,当表中存一些状态的字段,无非以下几种形式1.直接写死 如: 正常:1,异常:2 ,还有一种则是写在字典中,再或者就是加在枚举上,前两者对于返回下拉数据源来说比较 ...
- C++面试八股文:了解auto关键字吗?
某日二师兄参加XXX科技公司的C++工程师开发岗位第15面: 面试官:了解auto关键字吗? 二师兄:嗯,了解一些(我很熟悉). 面试官:说一说auto的用法吧? 二师兄:auto主要是为了编译器进行 ...
- 容器基础-- namespace,Cgoup 和 UnionFS
Namespace 什么是 Namespace ? 这里的 "namespace" 指的是 Linux namespace 技术,它是 Linux 内核实现的一种隔离方案.简而言之 ...
- 图扑 AR 技术应用与管理:施工建造、机柜扫描、办公室导航解决方案
随着科技的不断革新和创新,越来越多的行业开始迎来数字化时代的变革.建筑行业作为人类历史上最重要的产业之一,在数字化转型方面同样也在不断推进.图扑软件结合 AR 技术的应用,为建筑行业带来了更加便捷高效 ...
- Reactjs学习笔记
本篇是关于React的简介 ReactJS是Facebook推出的一款前端框架,2013年开源,提供了一种函数式编程思想,拥有比较健全的文档和完善的社区,在React16的版本中对算法进行了革新,称之 ...
- [Spring+SpringMVC+Mybatis]框架学习笔记(六):Spring_AspectJ实现AOP
第6章 Spring_AspectJ实现AOP 6.1 什么是AspectJ 对于AOP的这种编程思想,有很多框架或者组件进行了实现,spring实现AOP就是其中的一种. AspectJ也实现了AO ...