redis使用Geo找出GPS位置最近的坐标

3 篇文章 0 订阅

随着使用GPS坐标位置的手机或者设备越来越多,越来越多的应用使用gps坐标位置,为此redis增加了一种新的结构geo,可以很方便的计算最近距离的点。
首先添加pom.xml的jar包依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <!-- redis -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependencies>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.16</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

2、做一个添加坐标点,一个查询附近坐标点的查询方法


@RestController
@RequestMapping("redisGeo")
public class RedisGeoController {

    @Autowired
    private RedisGeoService redisGeoService;

    private final String GEO_KEY="geo_key";

    /**
     * 使用redis+geo 上传位置
     * @param cityId
     * @param driverId
     * @param lng
     * @param lat
     * @return
     */
    @PostMapping("addDriverPosition")
    public  Long addDriverPosition(String cityId,String driverId,Double lng,Double lat){
        String redisKey= CommonUtil.buildRedisKey(GEO_KEY,cityId);
        long addnum=redisGeoService.geoAdd(redisKey,new Point(lng,lat),driverId);
        List<Point> points=redisGeoService.geoGet(redisKey,driverId);
        System.out.println("添加坐标点的位置"+points);
        return  addnum;
    }

    /**
     * 使用reidis+geo 查找附近司机位置
     * @param cityId
     * @param lng
     * @param lat
     * @return
     */

    @GetMapping("getNearDrivers")
    public List<DriverPosition> getNearDrivers(String cityId,Double lng,Double lat){
        String redisKey=CommonUtil.buildRedisKey(GEO_KEY,cityId);
        Circle circle=new Circle(lng,lat, Metrics.KILOMETERS.getMultiplier());
        GeoResults<RedisGeoCommands.GeoLocation<String>> results=redisGeoService.nearByXY(redisKey,circle,5);
        System.out.println("查询附近司机位置"+results);

        List<DriverPosition> list =new ArrayList<>();
        results.forEach(item->{
            RedisGeoCommands.GeoLocation<String> location=item.getContent();
            Point point=location.getPoint();
            DriverPosition position=DriverPosition.builder().cityCode(cityId).driverId(location.getName()).lng(point.getX()).lat(point.getY()).build();
            list.add(position);
        });
        return  list;
    }




}

3、添加bean DriverPosition


import lombok.*;

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DriverPosition {
    private String driverId;
    private  String cityCode;
    private  double lng;
    private  double lat;
}

4、添加geo的service方法


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class RedisGeoService {

    @Autowired
    private StringRedisTemplate  redisTemplate;

    /**
     * 添加经纬度信息
     * redis 命令; geoadd key 120.223213 39.123123 "上海"
     * @param key
     * @param point
     * @param member
     * @return
     */
    public Long geoAdd(String key, Point point, String member){
        log.info((redisTemplate==null)+"=====");
        if(redisTemplate.hasKey(key)){
            redisTemplate.opsForGeo().remove(key,member);
        }
        return redisTemplate.opsForGeo().add(key,point,member);
    }

    /**
     * 根据key members批量获取坐标点
     *
     * redis 命令: geopos key 上海
     * @param key
     * @param members
     * @return
     */
    public List<Point> geoGet(String key, String... members){
        return redisTemplate.opsForGeo().position(key,members);
    }

    /**
     * 返回两个地方的距离,可以指定单位,比如:米m千米km,英里mi 英尺ft
     * redis 命令 : deodist key 北京 上海
     * @param key
     * @param member1
     * @param member2
     * @param metric
     * @return
     */
    public Distance geoDist(String key, String member1, String member2, Metric metric){
        return redisTemplate.opsForGeo().distance(key, member1, member2, metric);
    }

    /**
     * 根据给定的经纬度,返回半径不超过指定距离的元素
     *
     * redis命令 georedius key 116.2323 39.123123123 100 Km WITHDIST WITHCOORDASC COUNT 5
     * @param key
     * @param circle
     * @param count
     * @return
     */
    public GeoResults<RedisGeoCommands.GeoLocation<String>> nearByXY(String key, Circle circle, long count){
        // includeDIstance 包含距离
        // includeCoordinates 包含经纬度
        // sortAscending 正序排序
        // limit 限定返回的记录数
        RedisGeoCommands.GeoRadiusCommandArgs args=RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(count);
        return  redisTemplate.opsForGeo().radius(key, circle, args);
    }

    /**
     * 根据指定的地点查询半径在指定范围内的位置
     *
     * redis命令 : georadiusbymember key 北京 100 Km WITHDIST WITHCOORD ASC COUNT 5
     * @param key
     * @param member
     * @param distance
     * @param count
     * @return
     */
    public GeoResults<RedisGeoCommands.GeoLocation<String>> nearByPlace(String key,String member,Distance distance,long count){
        //includeDistance 包含距离
        //includeCoordinates 包含经纬度
        //sortAscending 正序排序
        //limit 限定返回的记录数
        RedisGeoCommands.GeoRadiusCommandArgs args=RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(count);
        return  redisTemplate.opsForGeo().radius(key,member,distance,args);
    }

    /**
     * 返回 geohash值
     * redis命令: geohash key 北京
     * @param key
     * @param member
     * @return
     */
    public  List<String> geoHash(String key,String member){
        return redisTemplate.opsForGeo().hash(key,member);
    }
}

5、添加application.yml文件

spring:
  redis:
    host: 127.0.0.1
    port: 6379
#    password: redis2020
    database: 1

第二部分:测试

1、使用postman调用增加坐标的方法

http://localhost:8080/redisGeo/addDriverPosition?cityId=420000&driverId=000001&lng=114.366386&lat=30.408199
http://localhost:8080/redisGeo/addDriverPosition?cityId=420000&driverId=000002&lng=114.365281&lat=30.406869
http://localhost:8080/redisGeo/addDriverPosition?cityId=420000&driverId=000003&lng=114.368049&lat=30.412896
http://localhost:8080/redisGeo/addDriverPosition?cityId=420000&driverId=000004&lng=114.365248&lat=30.537860

2.查看redis存的值
在这里插入图片描述
注意:如果调用redis遇到

io.lettuce.core.RedisCommandExecutionException: ERR unknown command 'GEOADD'

错误,说明自己windows版本的redis版本太低,需要下载更新版本的redis,大家可以下载redis4或者redis5的版本,下载地址:
https://github.com/tporadowski/redis/releases
3、调用查看附近坐标点的接口,查看是不是距离最近的坐标
在这里插入图片描述

参考文章:https://www.cnblogs.com/xuwenjin/p/12715339.html

完整的工程代码:
https://github.com/sunyuhuakeyboard/georedisdemo

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Spring Boot提供了对Redis的集成支持,可以使用Spring Data Redis来操作Redis。要在Spring Boot中使用RedisGEO功能,可以按照以下步骤进行操作: 1. 首先,确保在你的pom.xml(如果使用Maven)或build.gradle(如果使用Gradle)文件中添加以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 在application.properties或application.yml文件中配置Redis连接信息: ```yaml spring.redis.host=your-redis-host spring.redis.port=your-redis-port ``` 3. 创建一个实体类来表示地理位置信息,可以使用Spring Data Redis提供的`@RedisHash`和`@Indexed`注解来定义实体和索引,例如: ```java @RedisHash("locations") public class Location { @Id private String id; private String name; private Point point; // 用于存储地理位置的Point对象 // 省略构造方法、Getter和Setter } ``` 4. 创建一个继承自`CrudRepository`的Repository接口,用于对地理位置实体进行CRUD操作。可以使用Spring Data Redis提供的`@GeoIndexed`注解来定义地理位置索引,例如: ```java public interface LocationRepository extends CrudRepository<Location, String> { @GeoIndexed List<Location> findByPointNear(Point point, Distance distance); } ``` 5. 在需要使用地理位置功能的地方注入`LocationRepository`,然后就可以使用该Repository进行地理位置的操作了。例如,可以使用`findByPointNear`方法查询给定地理位置附近的其他位置,例如: ```java @Autowired private LocationRepository locationRepository; public List<Location> findNearbyLocations(Point point, double distance) { Distance searchDistance = new Distance(distance, Metrics.KILOMETERS); return locationRepository.findByPointNear(point, searchDistance); } ``` 这样,你就可以在Spring Boot中使用RedisGEO功能了。注意,以上只是一个简单的示例,实际使用中可能需要根据自己的业务需求进行适当的调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MonkeyKing.sun

对你有帮助的话,可以打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值