栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java > SpringBoot

SpringBoot 使用 Redis Geo

SpringBoot 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot 使用 Redis Geo

Redis GEO 的说明 Redis 官方对 Geo 的描述

Redis 3.2 contains significant changes to the API and implementation of Redis. A new set of commands for Geo indexing was added (GEOADD, GEORADIUS and related commands).

关于 Geo,需要知道

  • Redis 的 Geo 是在 3.2 版本才有的
  • 使用 geohash 保存地理位置的坐标
  • 使用有序集合(zset)保存地理位置的集合
6个操作命令
  • GEOADD:增加某个地理位置的坐标
  • GEOPOS:获取某个地理位置的坐标
  • GEODIST:获取两个地理位置的距离
  • GEORADIUS:根据给定地理位置坐标获取指定范围内的地理位置集合
  • GEORADIUSBYMEMBER:根据给定地理位置获取指定范围内的地理位置集合
  • GEOHASH:获取某个地理位置的 geohash 值
命令的使用方法
  • 官网
  • 黄健宏的文章
SpringBoot 使用 Redis Geo(实例)

说明:以城市信息为目标,使用 StringRedisTemplate 操作 Redis 提供的关于 Geo 的6个命令。

  • JDK 版本

		1.8

  • SpringBoot 版本

		org.springframework.boot
		spring-boot-starter-parent
		2.0.2.RELEASE
		

  • redis starter

		org.springframework.boot
		spring-boot-starter-data-redis

  • vo 对象定义
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CityInfo {

    
    private String city;

    
    private Double longitude;

    
    private Double latitude;
}
  • 服务接口定义
import com.imooc.ad.vo.CityInfo;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metric;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;

import java.util.Collection;
import java.util.List;


public interface IGeoService {

    
    Long saveCityInfoToRedis(Collection cityInfos);

    
    List getCityPos(String[] cities);

    
    Distance getTwoCityDistance(String city1, String city2, Metric metric);

    
    GeoResults> getPointRadius(
     Circle within, RedisGeoCommands.GeoRadiusCommandArgs args);

    
    GeoResults> getMemberRadius(
     String member, Distance distance, RedisGeoCommands.GeoRadiusCommandArgs args);

    
    List getCityGeoHash(String[] cities);
}
  • 服务接口实现
import com.alibaba.fastjson.JSON;
import com.imooc.ad.service.IGeoService;
import com.imooc.ad.vo.CityInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metric;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


@Slf4j
@Service
public class GeoServiceImpl implements IGeoService {

    private final String GEO_KEY = "ah-cities";

    
    private final StringRedisTemplate redisTemplate;

    @Autowired
    public GeoServiceImpl(StringRedisTemplate redisTemplate) {
 this.redisTemplate = redisTemplate;
    }

    @Override
    public Long saveCityInfoToRedis(Collection cityInfos) {

 log.info("start to save city info: {}.", JSON.toJSONString(cityInfos));

 GeoOperations ops = redisTemplate.opsForGeo();

 Set> locations = new HashSet<>();
 cityInfos.forEach(ci -> locations.add(new RedisGeoCommands.GeoLocation(
  ci.getCity(), new Point(ci.getLongitude(), ci.getLatitude())
 )));

 log.info("done to save city info.");

 return ops.add(GEO_KEY, locations);
    }

    @Override
    public List getCityPos(String[] cities) {

 GeoOperations ops = redisTemplate.opsForGeo();

 return ops.position(GEO_KEY, cities);
    }

    @Override
    public Distance getTwoCityDistance(String city1, String city2, Metric metric) {

 GeoOperations ops = redisTemplate.opsForGeo();

 return metric == null ?
     ops.distance(GEO_KEY, city1, city2) : ops.distance(GEO_KEY, city1, city2, metric);
    }

    @Override
    public GeoResults> getPointRadius(
     Circle within, RedisGeoCommands.GeoRadiusCommandArgs args
    ) {

 GeoOperations ops = redisTemplate.opsForGeo();

 return args == null ?
  ops.radius(GEO_KEY, within) : ops.radius(GEO_KEY, within, args);
    }

    @Override
    public GeoResults> getMemberRadius(
     String member, Distance distance, RedisGeoCommands.GeoRadiusCommandArgs args
    ) {

 GeoOperations ops = redisTemplate.opsForGeo();

 return args == null ?
  ops.radius(GEO_KEY, member, distance) : ops.radius(GEO_KEY, member, distance, args);
    }

    @Override
    public List getCityGeoHash(String[] cities) {

 GeoOperations ops = redisTemplate.opsForGeo();

 return ops.hash(GEO_KEY, cities);
    }
}
  • 测试用例
import com.alibaba.fastjson.JSON;
import com.imooc.ad.Application;
import com.imooc.ad.vo.CityInfo;
import org.junit.Before;
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.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class GeoServiceTest {

    
    private List cityInfos;

    @Autowired
    private IGeoService geoService;

    @Before
    public void init() {

 cityInfos = new ArrayList<>();

 cityInfos.add(new CityInfo("hefei", 117.17, 31.52));
 cityInfos.add(new CityInfo("anqing", 117.02, 30.31));
 cityInfos.add(new CityInfo("huaibei", 116.47, 33.57));
 cityInfos.add(new CityInfo("suzhou", 116.58, 33.38));
 cityInfos.add(new CityInfo("fuyang", 115.48, 32.54));
 cityInfos.add(new CityInfo("bengbu", 117.21, 32.56));
 cityInfos.add(new CityInfo("huangshan", 118.18, 29.43));
    }

    
    @Test
    public void testSaveCityInfoToRedis() {

 System.out.println(geoService.saveCityInfoToRedis(cityInfos));
    }

    
    @Test
    public void testGetCityPos() {

 System.out.println(JSON.toJSONString(geoService.getCityPos(
  Arrays.asList("anqing", "suzhou", "xxx").toArray(new String[3])
 )));
    }

    
    @Test
    public void testGetTwoCityDistance() {

 System.out.println(geoService.getTwoCityDistance("anqing", "suzhou", null).getValue());
 System.out.println(geoService.getTwoCityDistance("anqing", "suzhou", Metrics.KILOMETERS).getValue());
    }

    
    @Test
    public void testGetPointRadius() {

 Point center = new Point(cityInfos.get(0).getLongitude(), cityInfos.get(0).getLatitude());
 Distance radius = new Distance(200, Metrics.KILOMETERS);
 Circle within = new Circle(center, radius);

 System.out.println(JSON.toJSONString(geoService.getPointRadius(within, null)));

 // order by 距离 limit 2, 同时返回距离中心点的距离
 RedisGeoCommands.GeoRadiusCommandArgs args =
  RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().limit(2).sortAscending();
 System.out.println(JSON.toJSONString(geoService.getPointRadius(within, args)));
    }

    
    @Test
    public void testGetMemberRadius() {

 Distance radius = new Distance(200, Metrics.KILOMETERS);

 System.out.println(JSON.toJSONString(geoService.getMemberRadius("suzhou", radius, null)));

 // order by 距离 limit 2, 同时返回距离中心点的距离
 RedisGeoCommands.GeoRadiusCommandArgs args =
  RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().limit(2).sortAscending();
 System.out.println(JSON.toJSONString(geoService.getMemberRadius("suzhou", radius, args)));
    }

    
    @Test
    public void testGetCityGeoHash() {

 System.out.println(JSON.toJSONString(geoService.getCityGeoHash(
  Arrays.asList("anqing", "suzhou", "xxx").toArray(new String[3])
 )));
    }
}

欢迎关注课程:

基于 SpringCloud 微服务架构下 广告系统设计与实现

JAVA分布式优惠券系统后台 手把手实战开发

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号