redis计算经纬度距离
Posted 野生java研究僧
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis计算经纬度距离相关的知识,希望对你有一定的参考价值。
使用场景:
1.用户查询附近的酒店
2.游戏查看附件一起玩的人
3.交友app查看附件的人
注意:redis需要从3.2版本开始才支持
import lombok.NonNull;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
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.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.*;
/**
* redis经纬度计算工具类
*
* @author compass
* @date 2023-02-12
* @since 1.0
**/
@Component
public class GeoUtils
@Resource
private RedisTemplate<String, Object> redisTemplate;
public static final String GEO_CACHE_KEY = "geo_cache_key";
/**
* 将指定的地理空间位置(纬度、经度、名称)添加到指定的key中。
*
* @param cacheKey 缓存key
* @param point 经纬度位置
* @param certId 成员标识
* @return boolean
* @author compass
* @date 2023/2/12 23:39
* @since 1.0.0
**/
public boolean geoAdd(String cacheKey, Point point, String certId)
Long result = redisTemplate.opsForGeo().add(cacheKey, point, certId);
return result != null && result > 0;
/**
* 将经纬度信息添加到redis中
*
* @param cacheKey 缓存主键
* @param params params key为成员标识,value为经纬度信息
* @return boolean
* @author compass
* @date 2023/2/13 9:57
* @since 1.0.0
**/
public boolean geoAddAll(String cacheKey, Map<Object, Point> params)
GeoOperations<String, Object> ops = redisTemplate.opsForGeo();
Long result = ops.add(cacheKey, params);
return result != null && result > 0;
/**
* 计算两个人之间的距离
*
* @param cacheKey 缓存主键
* @param selfCertId 第一个标识
* @param otherCertId 第二个标识
* @return double
* @author compass
* @date 2023/2/13 10:23
* @since 1.0.0
**/
public double distanceBetween(String cacheKey, String selfCertId, String otherCertId)
GeoOperations<String, Object> geoOperations = redisTemplate.opsForGeo();
Distance distance = geoOperations.distance(cacheKey, selfCertId, otherCertId);
if (distance != null)
return distance.getValue();
return -1;
/**
* 查询距离某个人指定范围内的人,包括距离多少米
*
* @param cacheKey 缓存主键
* @param certId 目标标识
* @param distance 距离(米)
* @param limit 距离单位
* @param limit 限制个数
* @return java.util.Map<java.lang.String, java.lang.Double>
* @author compass
* @date 2023/2/13 9:59
* @since 1.0.0
**/
public Map<String, Double> distanceInclude(String cacheKey, String certId, double distance, long limit, RedisGeoCommands.DistanceUnit distanceUnit)
RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
.sortAscending()// 排序
.limit(limit)// 输出元素的个数
.includeCoordinates();// 输出经纬度
GeoResults<RedisGeoCommands.GeoLocation<Object>> geoResults = redisTemplate.opsForGeo().radius(cacheKey, certId, new Distance(distance, distanceUnit), geoRadiusCommandArgs);
HashMap<String, Double> resultMap = new HashMap<>();
if (geoResults != null)
List<GeoResult<RedisGeoCommands.GeoLocation<Object>>> content = geoResults.getContent();
for (GeoResult<RedisGeoCommands.GeoLocation<Object>> item : content)
RedisGeoCommands.@NonNull GeoLocation<Object> itemContent = item.getContent();
String otherCertId = itemContent.getName().toString();
double between = distanceBetween(cacheKey, certId, otherCertId);
resultMap.put(otherCertId, between);
return resultMap;
/**
* 查询距离某个人指定范围内的人,包括距离多少米
* @param cacheKey 缓存主键
* @param certId 目标标识
* @param distance 距离(米)
* @return java.util.Map<java.lang.String, java.lang.Double>
* @author compass
* @date 2023/2/13 11:06
* @since 1.0.0
**/
public Map<String, Double> distanceInclude(String cacheKey, String certId, double distance)
Map<String, Double> map = new LinkedHashMap<>();
GeoOperations geoOperations = redisTemplate.opsForGeo();
RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = geoOperations.radius(cacheKey, certId, new Distance(distance), geoRadiusCommandArgs.includeDistance());
if (geoResults != null)
Iterator<GeoResult<RedisGeoCommands.GeoLocation<String>>> iterator = geoResults.iterator();
while (iterator.hasNext())
GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult = iterator.next();
// 与目标点相距的距离信息
Distance geoResultDistance = geoResult.getDistance();
// 该点的信息
RedisGeoCommands.GeoLocation<String> geoResultContent = geoResult.getContent();
map.put(geoResultContent.getName(), geoResultDistance.getValue());
return map;
/**
* 获取指定目标的经纬度
*
* @param cacheKey 缓存主键
* @param certId 目标标识
* @return java.util.List<org.springframework.data.geo.Point>
* @author compass
* @date 2023/2/13 3:06
* @since 1.0.0
**/
public List<Point> position(String cacheKey, String certId)
return redisTemplate.opsForGeo().position(cacheKey, certId);
/**
* 将指定单位从geo中异常
*
* @param cacheKey 缓存主键
* @param certIds 成员标识
* @return boolean
* @author compass
* @date 2023/2/13 9:56
* @since 1.0.0
**/
public boolean remove(String cacheKey, String... certIds)
Long result = redisTemplate.opsForGeo().remove(cacheKey, certIds);
return result != null && result > 0;
/**
* 获取地理位置的哈希值
*
* @param cacheKey 缓存主键
* @param certIds 成员标识
* @return java.util.List<java.lang.String>
* @author compass
* @date 2023/2/13 10:22
* @since 1.0.0
**/
public List<String> hashByCertId(String cacheKey, String... certIds)
return redisTemplate.opsForGeo().hash(cacheKey, certIds);
以上是关于redis计算经纬度距离的主要内容,如果未能解决你的问题,请参考以下文章