Redis 地理坐标(GEO)方法使用详解

一、简介

  本文今天主要是地理坐标(GEO)的方法的使用,以及redis对应的Java实现该怎么用。因为篇幅问题,我这里写了一个测试类,引入 RedisTemplate对象,后面例子里就不一一引入了。大家理解就行,如果大家还不知道如何通过Spring Boot 整合redis则可以查看我之前的文章:SpringBoot整合redis(redis支持单节点和集群)

package com.alian.datastruct;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class RedisGeoTest {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
}

二、常用方法

2.1、GEOADD、GEOPOS

  • GEOADD 用于存储指定的地理空间位置的经度和纬度
  • GEOPOS 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度)

语法

ZADD KEY_NAME SCORE1 MEMBER1... SCOREn MEMBERn
GEOADD KEY_NAME longitude latitude member

命令操作

127.0.0.1:6379> geoadd geo1 113.883078 22.553291 shenzhen
(integer) 1
127.0.0.1:6379> geoadd geo1 113.273241 23.157921 guangzhou
(integer) 1
127.0.0.1:6379> geopos geo1 shenzhen guangzhou
1) 1) "113.88307839632034302"
   2) "22.55329111565713873"
2) 1) "113.27324062585830688"
   2) "23.1579209662846921"

Java操作

    @Test
    public void geoAddAndGeoPos() {
        String redisKey = "geo1";
        redisTemplate.delete(redisKey);
        // 设置深圳的坐标
        redisTemplate.opsForGeo().add(redisKey,new Point(113.883078,22.553291),"shenzhen");
        // 设置广州的坐标
        redisTemplate.opsForGeo().add(redisKey,new Point(113.273241,23.157921),"guangzhou");
        // 获取深圳的坐标
        List<Point> list = redisTemplate.opsForGeo().position(redisKey, "shenzhen","guangzhou");
        log.info("获取深圳的坐标:{}", list.get(0));
        log.info("获取广州的坐标:{}", list.get(1));
    }
获取深圳的坐标:Point [x=113.883078, y=22.553291]
获取广州的坐标:Point [x=113.273241, y=23.157921]

2.2、GEODIST

  • GEODIST 用于返回两个给定位置之间的直线距离

语法

GEODIST KEY_NAME member1 member2

命令操作

127.0.0.1:6379> geoadd geo2 113.883078 22.553291 shenzhen
(integer) 1
127.0.0.1:6379> geoadd geo2 113.273241 23.157921 guangzhou
(integer) 1
127.0.0.1:6379> geodist geo2 shenzhen guangzhou km
"91.8118"

Java操作

    @Test
    public void geoDist() {
        String redisKey = "geo2";
        redisTemplate.delete(redisKey);
        // 设置深圳的坐标
        redisTemplate.opsForGeo().add(redisKey,new Point(113.883078,22.553291),"shenzhen");
        // 设置广州的坐标
        redisTemplate.opsForGeo().add(redisKey,new Point(113.273241,23.157921),"guangzhou");
        // 获取两个城市之间的距离
        Distance distance = redisTemplate.opsForGeo().distance(redisKey, "shenzhen", "guangzhou", RedisGeoCommands.DistanceUnit.KILOMETERS);
        log.info("获取两个城市之间的距离:{} 千米", distance.getValue());
    }
获取两个城市之间的距离:91.8118 千米

2.3、GEORADIUS

  • GEORADIUS 根据给定的经纬度,返回半径不超过指定距离的元素

语法

GEORADIUS KEY_NAME longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

命令操作

127.0.0.1:6379> geoadd geo3 113.883078 22.553291 shenzhen
(integer) 1
127.0.0.1:6379> geoadd geo3 113.273241 23.157921 guangzhou
(integer) 1
127.0.0.1:6379> geoadd geo3 113.751791 23.020672 dongguan
(integer) 1
127.0.0.1:6379> geoadd geo3 113.392616 22.515951 zhongshan
(integer) 1
127.0.0.1:6379> georadius geo3 113.273241 23.157921 80 km
1) "guangzhou"
2) "dongguan"
3) "zhongshan"
127.0.0.1:6379> georadius geo3 113.273241 23.157921 80 km withdist
1) 1) "guangzhou"
   2) "0.0000"
2) 1) "dongguan"
   2) "51.2880"
3) 1) "zhongshan"
   2) "72.4447"

Java操作

    @Test
    public void geoRadius() {
        String redisKey = "geo3";
        redisTemplate.delete(redisKey);
        // 设置深圳的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.883078, 22.553291), "shenzhen");
        // 设置广州的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.273241, 23.157921), "guangzhou");
        // 设置东莞的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.751791, 23.020672), "dongguan");
        // 设置中山的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.392616, 22.515951), "zhongshan");
        // 以经纬度为中心,获取半径不超过最大距离的所有元素
        Point point = new Point(113.273241, 23.157921);
        // 半径为80km
        Distance distance = new Distance(80, RedisGeoCommands.DistanceUnit.KILOMETERS);
        Circle circle = new Circle(point, distance);
        GeoResults<RedisGeoCommands.GeoLocation<Object>> radius = redisTemplate.opsForGeo().radius(redisKey, circle);
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content= radius.getContent();
        for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult:content){
            RedisGeoCommands.GeoLocation<Object> geoResultContent = geoResult.getContent();
            log.info("获取半径不超过最大距离的所有元素:{}", geoResultContent.getName());
        }
    }
获取半径不超过最大距离的所有元素:guangzhou
获取半径不超过最大距离的所有元素:dongguan
获取半径不超过最大距离的所有元素:zhongshan

2.4、GEORADIUSBYMEMBER

  • GEORADIUSBYMEMBER 根据给定元素的经纬度,返回半径不超过指定距离的元素

语法

GEORADIUSBYMEMBER KEY_NAME member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

命令操作

127.0.0.1:6379> geoadd geo4 113.883078 22.553291 shenzhen
(integer) 1
127.0.0.1:6379> geoadd geo4 113.273241 23.157921 guangzhou
(integer) 1
127.0.0.1:6379> geoadd geo4 113.751791 23.020672 dongguan
(integer) 1
127.0.0.1:6379> geoadd geo4 113.392616 22.515951 zhongshan
(integer) 1
127.0.0.1:6379> georadiusbymember geo4 guangzhou 100 km withdist
1) 1) "guangzhou"
   2) "0.0000"
2) 1) "dongguan"
   2) "51.2880"
3) 1) "zhongshan"
   2) "72.4447"
4) 1) "shenzhen"
   2) "91.8118"

Java操作

    @Test
    public void geoRadiusByMember() {
        String redisKey = "geo4";
        redisTemplate.delete(redisKey);
        // 设置深圳的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.883078, 22.553291), "shenzhen");
        // 设置广州的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.273241, 23.157921), "guangzhou");
        // 设置东莞的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.751791, 23.020672), "dongguan");
        // 设置中山的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.392616, 22.515951), "zhongshan");
        // 定义距离
        Distance distance = new Distance(100, RedisGeoCommands.DistanceUnit.KILOMETERS);
        // 广州为中心点半径100km的元素
        GeoResults<RedisGeoCommands.GeoLocation<Object>> geoResults = redisTemplate.opsForGeo().radius(redisKey, "guangzhou", distance);
        List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content = geoResults.getContent();
        for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult : content) {
            RedisGeoCommands.GeoLocation<Object> geoResultContent = geoResult.getContent();
            log.info("广州为中心点半径100km的元素:{}", geoResultContent.getName());
        }
    }
广州为中心点半径100km的元素:guangzhou
广州为中心点半径100km的元素:dongguan
广州为中心点半径100km的元素:zhongshan
广州为中心点半径100km的元素:shenzhen

2.5、GEOHASH

  • GEOHASH 用于获取一个或多个位置元素的 geohash 值

语法

GEOHASH KEY_NAME member [member ...]

命令操作

127.0.0.1:6379> geoadd geo5 113.883078 22.553291 shenzhen
(integer) 1
127.0.0.1:6379> geoadd geo5 113.273241 23.157921 guangzhou
(integer) 1
127.0.0.1:6379> geoadd geo5 113.751791 23.020672 dongguan
(integer) 1
127.0.0.1:6379> geoadd geo5 113.392616 22.515951 zhongshan
(integer) 1
127.0.0.1:6379> geohash geo5 shenzhen guangzhou dongguan zhongshan
1) "ws0br3xnkn0"
2) "ws0e9xg09v0"
3) "ws0fuqz90u0"
4) "ws08h6cuzm0"

Java操作

    @Test
    public void geoHash() {
        String redisKey = "geo5";
        redisTemplate.delete(redisKey);
        // 设置深圳的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.883078, 22.553291), "shenzhen");
        // 设置广州的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.273241, 23.157921), "guangzhou");
        // 设置东莞的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.751791, 23.020672), "dongguan");
        // 设置中山的坐标
        redisTemplate.opsForGeo().add(redisKey, new Point(113.392616, 22.515951), "zhongshan");
        // 定义距离
        Distance distance = new Distance(100, RedisGeoCommands.DistanceUnit.KILOMETERS);
        // 获取各个城市的hash
        List<String> hashList = redisTemplate.opsForGeo().hash(redisKey, "shenzhen", "guangzhou", "dongguan", "zhongshan");
        log.info("获取各个城市的hash:{}", hashList);
    }
取各个城市的hash:[ws0br3xnkn0, ws0e9xg09v0, ws0fuqz90u0, ws08h6cuzm0]
  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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功能了。注意,以上只是一个简单的示例,实际使用中可能需要根据自己的业务需求进行适当的调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值