Java - 使用 Redis GEO 测算经纬度距离

本文介绍了如何利用Spring Data Redis的GeoOperations接口处理Redis的地理位置信息。通过`geoAdd`方法添加坐标,`distance`计算两点间距离,`radius`方法获取指定范围内的地理位置。示例代码展示了如何在Spring应用中整合RedisGEO,实现存储和检索经纬度信息以及获取距离等功能。

Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。

Redis GEO 操作方法有:

  • geoadd:添加地理位置的坐标。
  • geopos:获取地理位置的坐标。
  • geodist:计算两个位置之间的距离。
  • georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
  • georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
  • geohash:返回一个或多个位置对象的 geohash 值。

GeoOperations 的 add 方法

org.springframework.data.redis.core.GeoOperations

// Add RedisGeoCommands.GeoLocation into key.
Long add(K key, RedisGeoCommands.GeoLocation<M> location)

GeoOperations 的 distance 方法

org.springframework.data.redis.core.GeoOperations

// Get the Distance between member1 and member2.
Distance distance(K key, M member1, M member2)
spring 整合
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Distance;
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;

@Component
public class GeoUtil {
 
    @Autowired
    private RedisTemplate redisTemplate;
    
    /**
	 * 作为存储经纬度列表的key值
	 */
    private static final String GEO_KEY = "DISTANCE";
 
    /**
     * 将经纬度信息添加到redis中
     * @param certId 标识
     * @param longitude 经度
     * @param latitude 纬度
     */
    public void geoAdd(String certId, double longitude, double latitude) {
        GeoOperations geoOperations = redisTemplate.opsForGeo();
        Point point = new Point(longitude, latitude);
        RedisGeoCommands.GeoLocation geoLocation = new RedisGeoCommands.GeoLocation(certId, point);
        geoOperations.add(GEO_KEY, geoLocation);
    }
 
    /**
     * 两个人之间的距离
     * @param certId1
     * @param certId2
     * @return
     */
    public double distanceBetween(String certId1, String certId2) {
        GeoOperations geoOperations = redisTemplate.opsForGeo();
        Distance distance = geoOperations.distance(GEO_KEY, certId1, certId2);
        return distance.getValue();
    }
 
    /**
     * 查询距离某个人指定范围内的人,包括距离多少米
     * @param certId
     * @param distance
     * @return
     */
    public Map<String, Double> distanceInclude(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(GEO_KEY, 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;
    }
}
在 Spring Boot 中使用 RedisGEO 功能来计算两个地理位置之间的距离,可以通过 `Spring Data Redis` 提供的 API 实现。RedisGEO 功能基于 GeoHash 技术,支持存储地理位置信息并计算两个坐标点之间的距离。 要实现这一功能,需要以下几个步骤: ### 配置 Redis 依赖 在 `pom.xml` 文件中添加 `spring-boot-starter-data-redis` 和 `lettuce` 客户端依赖,确保能够使用 RedisGEO 功能: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> </dependency> ``` ### 使用 RedisTemplate 操作 GEO 在 Spring Boot 中,`RedisTemplate` 提供了对 Redis GEO 命令的支持。可以通过 `opsForGeo()` 方法获取 `GeoOperations` 实例,用于执行 GEOADD、GEODIST 等命令。 以下是一个示例代码,展示如何添加地理位置并计算两点之间的距离: ```java import org.springframework.data.geo.*; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.concurrent.TimeUnit; @Service public class GeoService { @Resource private RedisTemplate<String, String> redisTemplate; public void addLocation(String key, double longitude, double latitude, String member) { redisTemplate.opsForGeo().add(key, new Point(longitude, latitude), member); } public Double calculateDistance(String key, String member1, String member2, Metric metric) { return redisTemplate.opsForGeo().distance(key, member1, member2, metric); } } ``` ### 控制器示例 为了通过 HTTP 接口测试功能,可以创建一个简单的控制器类: ```java import org.springframework.web.bind.annotation.*; import org.springframework.data.geo.Metric; import org.springframework.data.geo.Metrics; @RestController @RequestMapping("/geo") public class GeoController { private final GeoService geoService; public GeoController(GeoService geoService) { this.geoService = geoService; } @PostMapping("/add") public String addLocation(@RequestParam String key, @RequestParam double longitude, @RequestParam double latitude, @RequestParam String member) { geoService.addLocation(key, longitude, latitude, member); return "Location added"; } @GetMapping("/distance") public Double getDistance(@RequestParam String key, @RequestParam String member1, @RequestParam String member2, @RequestParam String unit) { Metric metric = switch (unit.toLowerCase()) { case "km" -> Metrics.KILOMETERS; case "mi" -> Metrics.MILES; case "m" -> Metrics.METERS; case "ft" -> Metrics.FEET; default -> throw new IllegalArgumentException("Unknown unit: " + unit); }; return geoService.calculateDistance(key, member1, member2, metric); } } ``` ### 示例请求 - **添加位置**: ``` POST /geo/add?key=locations&longitude=116.405285&latitude=39.904989&member=Beijing ``` - **计算距离**: ``` GET /geo/distance?key=locations&member1=Beijing&member2=Shanghai&unit=km ``` 通过上述方式,可以在 Spring Boot 应用中使用 RedisGEO 功能来存储地理位置信息并计算两点之间的距离RedisGEO 功能基于经纬度存储,并支持多种单位(如公里、米、英里、英尺)的距离计算[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Whitemeen太白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值