redis GEO介绍及spring-boot中使用

1 介绍

GEO3.2.0之后版本 推出的新的数据结构,他的数据中保存的是地理位置数据,它可以用来计算两个坐标之间的举例和一个中心点范围内的坐标:比如最近门店,地图门店等
GEO底层数据结构 就是ZSET.
ZSET 存储多个元素 每个元素绑定一个score(score是float浮点类型).
(GEO底层原理)[https://blog.csdn.net/xingjigongsi/article/details/136233683]

2. 基本命令

2.1 GEOADD 添加坐标点

geo中添加坐标点
- GEOADD key longitude latitude member(Zadd key score member)


2.2 GEODIST 计算两个坐标点之间的距离

- GEODIST key member1 member2


2.3 GEORADIUS 查询中心点(lon lat) 半径(radius)之内的坐标

GEORADIUS key longitude latitude radius [m|km]

其他参数:

  • withcoord:返回结果中会包含 每个元素的地理位置.


  • withdist:展示每个元素 与参数中心点的距离数据.


  • withhash:将元素新增的时候 地理位置经过hash编码的结果附带元素返回


3 springboot使用

3.1 引入包

<!--spring-data-redis整合springboot依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

3.2装配Bean

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

@Configuration
public class RedisConfiguration {
    //创建2个RedisTemplate对象 用不同的序列化器
    @Bean("redis01")
    public RedisTemplate initRedis01(RedisConnectionFactory factory){
        RedisTemplate redisTemplate=new RedisTemplate();
        redisTemplate.setConnectionFactory(factory);
        //自定义序列化 操作redis 操作key value 考虑hash key value field
        //key值必须在客户端传递String类型数据,然后通过底层对string字符串做序列化
        redisTemplate.setKeySerializer(RedisSerializer.string());
        //value必须是String类型,因为客户端要使用string的序列化
        redisTemplate.setValueSerializer(RedisSerializer.string());
        return redisTemplate;
    }
    @Bean("redis02")
    public RedisTemplate initRedis02(RedisConnectionFactory factory){
        RedisTemplate redisTemplate=new RedisTemplate();
        redisTemplate.setConnectionFactory(factory);
        //自定义序列化 操作redis 操作key value 考虑hash key value field
        //key值可以是java中任意Object类型,但是必须支持Searlizable接口
        redisTemplate.setKeySerializer(RedisSerializer.java());
        //value值可以是java中任意Object类型,但是必须支持Searlizable接口
        redisTemplate.setValueSerializer(RedisSerializer.java());
        return redisTemplate;
    }
}

3.3使用测试

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.domain.geo.GeoLocation;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

//如果测试类和启动类在同包名下 属性无需添加
//如果包不同 需要指定启动类
@SpringBootTest(classes=RedisDemoApp.class)
public class RedisDemoGeoTest {
    @Resource
    @Qualifier("redis02")
    private RedisTemplate redisClient;
    //操作写入geo数据
    @Test
    public void geoAdd(){
        //geoadd stations 116 39 station_01
        /*redisClient.boundGeoOps("stations").add()*/
        //操作geo类型 需要获取二级对象 opsForGeo
        GeoOperations geoOps = redisClient.opsForGeo();
        //将数据封装 一种api的参数格式,将经纬度封装成 Point 精度在api x 维度在api y
        /*Point point=new Point(116,39);
        geoOps.add("stations",point,"station_01");*/
        //geoadd station 116 39 station_01 117 40 station_02 118 41 station_03
        List<RedisGeoCommands.GeoLocation> members=new ArrayList<>();
        members.add(new RedisGeoCommands.GeoLocation("station_01",new Point(116,39)));
        members.add(new RedisGeoCommands.GeoLocation("station_02",new Point(117,40)));
        members.add(new RedisGeoCommands.GeoLocation("station_03",new Point(118,41)));
        geoOps.add("stations",members);
        //key值一般都是string数据 但是value元素 可以是任意类型
    }
    //geodist测试
    @Test
    public void geoDist(){
        //操作geo的二级对象
        GeoOperations geoOps = redisClient.opsForGeo();
        //操作的stations
        String key="stations";
        //geodist key member1 member2 m|km|ft|mi 默认是米
        Distance distance01 = geoOps.distance(key, "station_01", "station_02");
        //geodist key member2 member3 KM 指定公里
        //m km ft mi 可以提供一个枚举对象的
        Distance distance02 = geoOps.distance(key, "station_02", "station_03",
                RedisGeoCommands.DistanceUnit.KILOMETERS);
        //可以解析两个返回值 区别就是单位
        System.out.println("station01距离station02:"+distance01.getValue()+"M");//M
        System.out.println("station02距离station03:"+distance02.getValue()+"KM");//KM
    }
    //georadius withcoord withdist withhash
    @Test
    public void geoRadius(){
        //操作geo的二级对象
        GeoOperations geoOps = redisClient.opsForGeo();
        //操作的stations
        String key="stations";
        //georadius stations 116 39 500 km 从返回值 获取到元素(泛型方便 没有泛型强转)
        //客户端的radius方法中 有2个方法是以元素地理位置为中心点查询半径 不满足我们业务的需求
        //自定义中心的Circle封装
        Circle center=new Circle(116.00,39.00,200000.00);
        GeoResults all = geoOps.radius(key, center);
        //解析数据 获取results中所有命中元素集合
        List results = all.getContent();
        for (Object result : results) {
            //每个元素类型是GeoResult
            GeoResult geoItem = (GeoResult) result;
            //如果查询命令 携带了withdist 其中distance可以解析 如果没有携带 distance空值
            Distance distance = geoItem.getDistance();
            //获取绑定地理位置的元素对象 domain.geo包
            GeoLocation location=(GeoLocation)geoItem.getContent();
            //从location获取绑定元素的地理位置point 但是必须在添加命令选项 withcoord
            Point point = location.getPoint();
            String stationMember=(String)location.getName();//写数据的元素
            System.out.println("元素值:"+stationMember);
        }
    }
    //客户端定义泛型 少做强转
    @Test
    public void geoRadiusWithClass(){
        //泛型的格式是固定 只需要关注 geo的key 以及元素
        GeoOperations geoOps = redisClient.opsForGeo();
        //操作的stations
        String key="stations";
        Circle center=new Circle(116.00,39.00,200000.00);
        GeoResults<GeoLocation<String>> all = geoOps.radius(key, center);
        //解析数据 获取results中所有命中元素集合
        List<GeoResult<GeoLocation<String>>> results = all.getContent();
        for (GeoResult<GeoLocation<String>> result : results) {
            GeoLocation<String> location = result.getContent();
            Distance distance = result.getDistance();
            Point point = location.getPoint();
            String member = location.getName();
            System.out.println("元素值:"+member);
        }
    }
    //withcoord withdist
    @Test
    public void geoRadiusWithArgs(){
        //泛型的格式是固定 只需要关注 geo的key 以及元素
        GeoOperations geoOps = redisClient.opsForGeo();
        //操作的stations
        String key="stations";
        Circle center=new Circle(116.00,39.00,200000.00);
        //增加georadius命令选项 withcoord withdist
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        //args添加选项
        args.includeCoordinates();//withcoord
        args.includeDistance();//withdist
        //args.sortAscending();//SORT ASC|DESC 以元素距离中心点位移排序 必须保证redis中间件支持的
        GeoResults<GeoLocation<String>> all = geoOps.radius(key, center,args);
        //解析数据 获取results中所有命中元素集合
        List<GeoResult<GeoLocation<String>>> results = all.getContent();
        for (GeoResult<GeoLocation<String>> result : results) {
            GeoLocation<String> location = result.getContent();
            Distance distance = result.getDistance();
            Point point = location.getPoint();
            String member = location.getName();
            System.out.println("元素值:"+member);
            System.out.println("距离中心点位移:"+distance.getValue()+distance.getUnit());
            System.out.println("元素地理位置:经度"+point.getX()+",维度"+point.getY());
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容