Redis GEO实现附近搜索功能


    公司最近来了一个新项目,做小程序招聘。其中有一个需求是实现附近岗位推荐。由于用户量不大,决定采用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实现附近搜索功能的文章就介绍到这了,更多相关Redis GEO附近搜索内容请搜索电脑手机教程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持电脑手机教程网!