博主
258
258
258
258
专辑

第十八节 Springboot中操作Redis的Geo类型

亮子 2021-07-08 01:36:20 1280 0 0 0

1、添加maven依赖

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

2、Geo简介

关于 Geo,需要知道

Redis 的 Geo 是在 3.2 版本才有的
使用 geohash 保存地理位置的坐标
使用有序集合(zset)保存地理位置的集合

6个操作命令

  • GEOADD:增加某个地理位置的坐标
  • GEOPOS:获取某个地理位置的坐标
  • GEODIST:获取两个地理位置的距离
  • GEORADIUS:根据给定地理位置坐标获取指定范围内的地理位置集合
  • GEORADIUSBYMEMBER:根据给定地理位置获取指定范围内的地理位置集合
  • GEOHASH:获取某个地理位置的 geohash 值

3、坐标对象

@Data
@NoArgsConstructor
@AllArgsConstructor
class UserNews {
    private Long id;                // 用户ID
    private Double longitude;       // 经度
    private Double latitude;        // 纬度

}

4、操作Geo

@SpringBootTest
public class RedisGeoTest {

    @Autowired
    RedisTemplate redisTemplate;

    @Test
    void testAddGeo() {
        //--1 把位置信息存入hash
        UserNews userNews1 = new UserNews();
        userNews1.setId(1L);
        // 116.307594,40.048617
        userNews1.setLongitude(116.307594);
        userNews1.setLatitude(40.048617);

        RedisGeoCommands.GeoLocation<Long> longGeoLocation1 = new RedisGeoCommands.GeoLocation<>(userNews1.getId(), new Point(userNews1.getLongitude(), userNews1.getLatitude()));

        redisTemplate.opsForGeo().add("geo_user", longGeoLocation1);

        //
        UserNews userNews2 = new UserNews();
        userNews2.setId(2L);
        // 116.306193,40.045814
        userNews2.setLongitude(116.306193);
        userNews2.setLatitude(40.045814);

        RedisGeoCommands.GeoLocation<Long> longGeoLocation2 = new RedisGeoCommands.GeoLocation<>(
                userNews2.getId(), new Point(userNews2.getLongitude(), userNews2.getLatitude()));

        redisTemplate.opsForGeo().add("geo_user", longGeoLocation2);

        //
        UserNews userNews3 = new UserNews();
        userNews3.setId(3L);
        // 116.30551,40.047899
        userNews3.setLongitude(116.30551);
        userNews3.setLatitude(40.047899);

        RedisGeoCommands.GeoLocation<Long> longGeoLocation3 = new RedisGeoCommands.GeoLocation<>(
                userNews3.getId(), new Point(userNews3.getLongitude(), userNews3.getLatitude()));

        redisTemplate.opsForGeo().add("geo_user", longGeoLocation3);

        Long geo_size = redisTemplate.opsForZSet().size("geo_user");
        System.out.println("geo_size="+geo_size);

    }

    @Test
    void testGeoPosition() {
        //--2 获取某个用户的地理位置信息

        List<Point> userList = redisTemplate.opsForGeo().position("geo_user", 2L, 3L);
        userList.forEach(user->{
            System.out.println(user);
        });
    }

    @Test
    void testGeoDistance() {
        //--3 获取某两个用户之间的距离

        Distance geo_distance = redisTemplate.opsForGeo().distance("geo_user", 2L, 3L);
        System.out.println(geo_distance);

        Distance geo_distance2 = redisTemplate.opsForGeo().distance("geo_user", 2L, 3L, Metrics.KILOMETERS);
        System.out.println(geo_distance2);
    }

    @Test
    void testGeoCircle() {
        //--4 根据一个点,获取方圆一定范围内的所有用户信息

        Point center = new Point(116.306965,40.047554);
        Distance distance = new Distance(2, Metrics.KILOMETERS);

        Circle circle = new Circle(center, distance);

        GeoResults<RedisGeoCommands.GeoLocation<Long>> users = redisTemplate.opsForGeo().radius("geo_user", circle);
        List<GeoResult<RedisGeoCommands.GeoLocation<Long>>> contents = users.getContent();
        contents.forEach(content->{
            System.out.println(content);
            RedisGeoCommands.@NonNull GeoLocation<Long> user = content.getContent();
            System.out.println("userid="+user.getName());
        });
    }

    @Test
    void testGeoCircle2() {
        Point center = new Point(116.306965,40.047554);
        Distance distance = new Distance(2, Metrics.KILOMETERS);

        Circle circle = new Circle(center, distance);

        // 包含距离、包含坐标、升序排列、只返回5个
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance()
                .includeCoordinates()
                .sortAscending()
                .limit(5);

        GeoResults<RedisGeoCommands.GeoLocation<Long>> users = redisTemplate.opsForGeo().radius("geo_user", circle, args);
        List<GeoResult<RedisGeoCommands.GeoLocation<Long>>> contents = users.getContent();
        contents.forEach(content->{
            System.out.println(content);

            RedisGeoCommands.@NonNull GeoLocation<Long> user = content.getContent();
            System.out.println(user);
        });
    }
}