RedisGEO实现附近搜索功能

2024-12-23 18:04:13 来源/作者: 这里教程网 /

公司最近来了一个新项目,做小程序招聘。其中有一个需求是实现附近岗位推荐。由于用户量不大,决定采用redis来实现。之前没有接触过。现在用来记录一下。(redis必须使用3.2及以上版本)

先说一下大概流程。将职位ID和经纬度存入redis中。每当添加职位时就增加一条信息。当用户点击附近时,通过用户的经纬度来查询它对应的职位id,这样就可以关联起来查询出职位信息返回用户给予展示。项目采用的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("经度") private Double longitude; @ApiModelProperty("纬度") private Double latitude; @ApiModelProperty("半径") private Double radius; @ApiModelProperty("条数") 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; /** * 初始化数据可以将职位id和经纬度存入redis, * 添加职业时增加位置数据 * 当用户点击附近是,传入经纬度。返回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); //设置参数 包括距离、坐标、条数 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); } }

测试数据

### 使用的是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

上传的只是练习项目,同理只需要将城市名称换成职业id即可

到此这篇关于Redis GEO实现附近搜索功能的文章就介绍到这了,