Redis GEO實現(xiàn)附近搜索功能
公司最近來了一個新項目,做小程序招聘。其中有一個需求是實現(xiàn)附近崗位推薦。由于用戶量不大,決定采用redis來實現(xiàn)。之前沒有接觸過?,F(xiàn)在用來記錄一下。(redis必須使用3.2及以上版本)
- 先說一下大概流程。將職位ID和經(jīng)緯度存入redis中。每當添加職位時就增加一條信息。當用戶點擊附近時,通過用戶的經(jīng)緯度來查詢它對應的職位id,這樣就可以關聯(lián)起來查詢出職位信息返回用戶給予展示。
- 項目采用的spring cloud Alibaba全家桶,就不寫它的maven依賴,只編寫redis相關
引入redis依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.3.0.RELEASE</version>
</dependency>Bo
package cn.zxw.vo_bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @Author: zhangxiongwei
* @Date: 2021-10-26 16:11
* @Description: 位置信息
*/
@Data
@ApiModel("位置信息")
public class LocationBo {
@ApiModelProperty("經(jīng)度")
private Double longitude;
@ApiModelProperty("緯度")
private Double latitude;
@ApiModelProperty("半徑")
private Double radius;
@ApiModelProperty("條數(shù)")
private Long limit;
}redis配置類
package cn.zxw.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
/**
* @Author: zhangxiongwei
* @Date: 2021-10-26 16:38
* @Description: redi配置
*/
@Configuration
public class RedisConfig {
/**
* The constant GEO_STAGE.
*/
public static final String GEO_STAGE = "cities";
/**
* Geo ops bound geo operations.
*
* @param redisTemplate the redis template
* @return the bound geo operations
*/
@Bean
public BoundGeoOperations<String, String> citiesGeoOps(RedisTemplate<String, String> redisTemplate) {
// 清理緩存
redisTemplate.delete(GEO_STAGE);
return redisTemplate.boundGeoOps(GEO_STAGE);
}
}測試控制器
package cn.zxw.controller;
import cn.zxw.result.CommonResult;
import cn.zxw.vo_bo.LocationBo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: zhangxiongwei
* @Date: 2021-10-26 15:41
* @Description: 附近推薦
*/
@Slf4j
@RestController
@Api(tags = "redis", description = "redis控制")
@RequestMapping("/geo")
@AllArgsConstructor
public class RedisGeoController {
private static final String GEO_STAGE = "cities";
private final RedisTemplate<String, String> redisTemplate;
private final BoundGeoOperations<String, String> citiesGeoOps;
/**
* 初始化數(shù)據(jù)可以將職位id和經(jīng)緯度存入redis,
* 添加職業(yè)時增加位置數(shù)據(jù)
* 當用戶點擊附近是,傳入經(jīng)緯度。返回id獲得職位信息推送給用戶
*/
@GetMapping("/init")
@ApiOperation("初始化")
public void init() {
// 清理緩存
redisTemplate.delete(GEO_STAGE);
Map<String, Point> points = new HashMap<>();
points.put("shijiazhuang", new Point(114.48, 38.03));
points.put("xingtang", new Point(114.54, 38.42));
points.put("guangcheng", new Point(114.84, 38.03));
points.put("gaoyi", new Point(114.58, 37.62));
points.put("zhaoxian", new Point(114.78, 37.76));
points.put("jinxing", new Point(114.13, 38.03));
points.put("luquan", new Point(114.03, 38.08));
points.put("xinle", new Point(114.67, 38.33));
points.put("zhengding", new Point(114.56, 38.13));
// 添加地理信息
redisTemplate.boundGeoOps(GEO_STAGE).add(points);
}
@PostMapping("/city")
@ApiOperation("獲得城市")
public CommonResult<GeoResults<RedisGeoCommands.GeoLocation<String>>> dis(@RequestBody LocationBo locationBo) {
//設置當前位置
Point point = new Point(locationBo.getLongitude(), locationBo.getLatitude());
//設置半徑范圍
Metric metric = RedisGeoCommands.DistanceUnit.METERS;
Distance distance = new Distance(locationBo.getRadius(), metric);
Circle circle = new Circle(point, distance);
//設置參數(shù) 包括距離、坐標、條數(shù)
RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands
.GeoRadiusCommandArgs
.newGeoRadiusArgs()
.includeDistance()
.includeCoordinates()
.sortAscending()
.limit(locationBo.getLimit());
GeoResults<RedisGeoCommands.GeoLocation<String>> radius = citiesGeoOps.radius(circle, args);
return CommonResult.success(radius);
}
}測試數(shù)據(jù)
### 使用的是httpclient
POST http://localhost:6001/geo/city
Content-Type: application/json
{
"longitude": 114.56,
"latitude": 38.13,
"radius": 100000,
"limit": 10
}返回結果
{
"code": 200,
"message": "操作成功",
"data": {
"averageDistance": {
"value": 31642.19217777778,
"metric": "METERS",
"unit": "m",
"normalizedValue": 0.004961039905191403
},
"content": [
{
"content": {
"name": "zhengding",
"point": {
"x": 114.55999821424484,
"y": 38.12999923666221
}
},
"distance": {
"value": 0.1778,
"metric": "METERS",
"unit": "m",
"normalizedValue": 2.787647866453794E-8
}
},
{
"content": {
"name": "shijiazhuang",
"point": {
"x": 114.55999821424484,
"y": 38.02999941748397
}
},
"distance": {
"value": 13144.3531,
"metric": "METERS",
"unit": "m",
"normalizedValue": 0.0020608452123245394
}
},
{
"content": {
"name": "xinle",
"point": {
"x": 114.55999821424484,
"y": 38.329998875018696
}
},
"distance": {
"value": 24232.5609,
"metric": "METERS",
"unit": "m",
"normalizedValue": 0.0037993164618445796
}
},
{
"content": {
"name": "guangcheng",
"point": {
"x": 114.55999821424484,
"y": 38.02999941748397
}
},
"distance": {
"value": 26919.7324,
"metric": "METERS",
"unit": "m",
"normalizedValue": 0.004220626242427844
}
},
{
"content": {
"name": "xingtang",
"point": {
"x": 114.55999821424484,
"y": 38.419999219223335
}
},
"distance": {
"value": 32302.7819,
"metric": "METERS",
"unit": "m",
"normalizedValue": 0.005064610857371048
}
},
{
"content": {
"name": "jinxing",
"point": {
"x": 114.55999821424484,
"y": 38.02999941748397
}
},
"distance": {
"value": 39255.7243,
"metric": "METERS",
"unit": "m",
"normalizedValue": 0.006154732063610425
}
},
{
"content": {
"name": "zhaoxian",
"point": {
"x": 114.55999821424484,
"y": 37.760000919591185
}
},
"distance": {
"value": 45453.0791,
"metric": "METERS",
"unit": "m",
"normalizedValue": 0.007126388018946599
}
},
{
"content": {
"name": "luquan",
"point": {
"x": 114.55999821424484,
"y": 38.07999932707309
}
},
"distance": {
"value": 46718.8049,
"metric": "METERS",
"unit": "m",
"normalizedValue": 0.00732483559070619
}
},
{
"content": {
"name": "gaoyi",
"point": {
"x": 114.55999821424484,
"y": 37.62000066579741
}
},
"distance": {
"value": 56752.5152,
"metric": "METERS",
"unit": "m",
"normalizedValue": 0.00889797682301274
}
}
]
}
}Response code: 200; Time: 92ms; Content length: 1844 bytes
上傳的只是練習項目,同理只需要將城市名稱換成職業(yè)id即可
到此這篇關于Redis GEO實現(xiàn)附近搜索功能的文章就介紹到這了,更多相關Redis GEO附近搜索內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解Redis BoundValueOperations使用及實現(xiàn)
BoundValueOperations是Spring Data Redis中一個非常實用的工具,本文主要介紹了Redis BoundValueOperations使用,具有一定的參考價值,感興趣的可以了解一下2025-09-09
Redis中redis-shake實現(xiàn)數(shù)據(jù)遷移同步
在業(yè)務環(huán)境中使用Redis進行跨區(qū)域數(shù)據(jù)遷移和同步的挑戰(zhàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-11-11
Redis哨兵模式在Spring Boot項目中的使用與實踐完全指南
Redis哨兵模式為SpringBoot項目提供高可用Redis管理,實現(xiàn)自動故障轉(zhuǎn)移與監(jiān)控,通過配置依賴、參數(shù)及最佳實踐(如哨兵節(jié)點數(shù)量、網(wǎng)絡規(guī)劃),可提升系統(tǒng)穩(wěn)定性與可靠性,本文給大家介紹Redis哨兵模式在Spring Boot項目中的使用與實踐,感興趣的朋友跟隨小編一起看看吧2025-09-09

