一、概述
Redis Geo是Redis中专门用于处理地理位置数据的模块,它利用有序集合Sorted Set和Geohash编码技术存储经纬度信息。
核心功能包括:
1.GEOADD添加地理坐标;
2.GEODIST计算两点间距离;
3.GEORADIUS或GEORADIUSBYMEMBER搜索指定半径内的位置。
这些特性使得Redis Geo在实现如“查找附近的人或地点、计算间隔距离”等功能时表现出色,特别适用于需要高效地理空间查询的应用场景。
二、依赖
使用restTemplate的方式,可以更方便的使用redis其它功能。
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
三、RedisGeo工具类
package com.jwzj.redisdemo.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.data.redis.core.RedisTemplate;
import java.util.List;
/**
* RedisGeo工具类
*
* @author CQller
*/
@Configuration
public class RedisGeoUtil {
/**
* 地点A经纬度在redis中key前缀
*/
public static final String DEALER_PREFIX_KEY = "GEO:AREA_LONGITUDE_AND_LATITUDE";
/**
* redisTemplate。
*/
private RedisTemplate<String, Object> redisTemplate;
/**
* 自动装配redisTemplate。
*
* @param redisTemplate redisTemplate
*/
@Autowired
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* Redis添加地点A经纬度
*
* @param longitude 经度
* @param latitude 纬度
* @param name 位置名称
* @return {@link Long}
*/
public Long redisGerAdd(double longitude, double latitude, String name) {
return redisTemplate.opsForGeo().add(DEALER_PREFIX_KEY, new Point(longitude, latitude), name);
}
/**
* 经纬度查距离最近的地点A
*
* @param lon 经度
* @param lat 纬度
* @return {@link Object}
*/
public Object recentDealer(double lon, double lat) {
Circle circle = new Circle(lon, lat, Metrics.KILOMETERS.getMultiplier());
RedisGeoCommands.GeoRadiusCommandArgs args;
args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
.includeDistance().includeCoordinates().sortAscending().limit(1);
return redisTemplate.opsForGeo().radius(DEALER_PREFIX_KEY, circle, args);
}
/**
* 删除指定名称地点A
*
* @param dealerName 地点A名称
* @return {@link List<String>}
*/
public Long delRedisGeo(String dealerName) {
return redisTemplate.opsForZSet().remove(DEALER_PREFIX_KEY, dealerName);
}
/**
* 获得经纬度
*
* @param key 键名
* @param nameList 位置名称集合
* @return {@link List <Point>}
*/
public List<Point> redisGeoGet(String key, List<String> nameList) {
return redisTemplate.opsForGeo().position(key, nameList.toArray());
}
/**
* 获得两点之间距离
*
* @param key 键名
* @param name1 位置1
* @param name2 位置2
* @return {@link Distance}
*/
public Distance redisGeoDist(String key, String name1, String name2) {
return redisTemplate.opsForGeo().distance(key, name1, name2, RedisGeoCommands.DistanceUnit.KILOMETERS);
}
/**
* 根据位置名称获得指定距离的位置信息
*
* @param key 键名
* @param name 位置名称
* @param distance 距离
* @param count 数
* @return {@link Object}
*/
public Object redisGeoRadius(String key, String name, Double distance, int count) {
RedisGeoCommands.GeoRadiusCommandArgs args;
args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(count);
return redisTemplate.opsForGeo().radius(key, name, new Distance(distance, Metrics.KILOMETERS), args);
}
/**
* 获得位置geohash表示
*
* @param key 键名
* @param nameList 位置名称
* @return {@link List<String>}
*/
public List<String> redisGeoHash(String key, List<String> nameList) {
return redisTemplate.opsForGeo().hash(key, nameList.toArray());
}
/**
* 根据key清除数据
*
* @param key 键
* @return {@link List<String>}
*/
public Boolean del(String key) {
System.out.println(DEALER_PREFIX_KEY.replace("{dealerId}", key));
return redisTemplate.delete(DEALER_PREFIX_KEY.replace("{dealerId}", key));
}
}
四、请求结果演示
调用redisGerAdd方法分别录入两个位置的经纬度后,
使用redisGeoDist方法计算两点之间的距离: