Java集成RedisGeo计算两点之间的距离

一、概述

        Redis Geo是Redis中专门用于处理地理位置数据的模块,它利用有序集合Sorted Set和Geohash编码技术存储经纬度信息。

        核心功能包括:

        1.GEOADD添加地理坐标

        2.GEODIST计算两点间距离

        3.GEORADIUSGEORADIUSBYMEMBER搜索指定半径内的位置。

        这些特性使得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方法计算两点之间的距离:

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值