使用redisTemplate-geo计算经纬度距离

简介

业务中常有需求是计算经纬度之间的距离,redis是使用较多的缓存中间件,正好有关于geo位置计算的api,可以直接拿来用.

redis依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
redis:
  host: xxx.xxx.xxx.xxx
  port: 36379
  password: xxx
  database: 0
  jedis:
    pool:
      max-idle: 10
      max-wait: 3000
      max-active: 50
      min-idle: 5
  timeout: 30000

demo展示

直接上demo代码

package com.felix.spring_cloud_one.service;

import com.felix.spring_cloud_one.params.SaveGeoPointVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class RedisGeoService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public Object saveGeoPoint(List<SaveGeoPointVO> vos) {
        String city = vos.get(0).getCity();
        Map<String, Point> map;
        map = vos.stream().collect(Collectors.toMap(SaveGeoPointVO::getName, it -> new Point(it.getLgt(), it.getLat())));
        Long add = stringRedisTemplate.opsForGeo().add(city, map);
        return add;
    }

    public Object getGeoPoint(SaveGeoPointVO vo) {
        List<Point> position = getGeoPoint(vo.getCity(), vo.getName());
        return position;
    }

    /**
     * [
     *     {
     *         "x": 120.11999756097794,
     *         "y": 41.079998971862615
     *     }
     * ]
     * @param city
     * @param members
     * @return
     */
    //查找指定key的经纬度信息,可以指定多个member,批量返回
    private List<Point> getGeoPoint(String city, String ... members) {
        List<Point> position = stringRedisTemplate.opsForGeo()
                .position(
                        city,
                        members
                );
        return position;
    }

    /**
     * {
     *     "value": 925.2986,
     *     "metric": "KILOMETERS"
     * }
     */
    //获取一个key下的2个位置点的距离
    public Distance getDistance(String city, String members1, String members2, Metric metric){
        if(Objects.isNull(metric)){
            metric = Metrics.KILOMETERS;
        }
        Distance distance = stringRedisTemplate.opsForGeo().distance(city, members1, members2, metric);
        return distance;
    }

    //redis命令:georadius key 116.405285 39.904989 100 km WITHDIST WITHCOORD ASC
    //根据给定的经纬度返回半径范围内不超过指定距离的元素
    public Object nearByXY(String city, Circle circle, long count){
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                //包含距离
                .includeDistance()
                //包含经纬度
                .includeCoordinates()
                //升序
                .sortAscending()
                .limit(count);

        GeoResults<RedisGeoCommands.GeoLocation<String>> radius = stringRedisTemplate.opsForGeo().radius(city, circle, args);
        return radius;
    }

    /**
     * {
     *     "averageDistance": {
     *         "value": 193.9615,
     *         "metric": "KILOMETERS"
     *     },
     *     "content": [
     *         {
     *             "content": {
     *                 "name": "2",
     *                 "point": {
     *                     "x": 120.11999756097794,
     *                     "y": 41.079998971862615
     *                 }
     *             },
     *             "distance": {
     *                 "value": 120.5517,
     *                 "metric": "KILOMETERS"
     *             }
     *         },
     *         {
     *             "content": {
     *                 "name": "3",
     *                 "point": {
     *                     "x": 117.12000042200089,
     *                     "y": 39.080000053576654
     *                 }
     *             },
     *             "distance": {
     *                 "value": 267.3713,
     *                 "metric": "KILOMETERS"
     *             }
     *         }
     *     ]
     * }
     */
    public Object nearByXY(String city, Double lng, Double lat, double distanceNum, long count){
        Point point = new Point(lng, lat);
        Distance distance = new Distance(distanceNum, Metrics.KILOMETERS);
        Circle circle = new Circle(point, distance);
        Object result = nearByXY(city, circle, count);
        return result;
    }


    //删除
    //GEO数据本质上是放到一个zset集合里了 
	//删除可以用 ZREM key member
    public Boolean deleteByMembers(String city, String... members){
        Long remove = stringRedisTemplate.opsForGeo().remove(city, members);
        return remove.intValue() == members.length;
    }

}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RedisTemplate可以用于执行GEO命令,GEORedis提供的一种地理位置信息处理方式。以下是RedisTemplate GEO命令的使用示例: 1. 添加地理位置信息 ```java RedisGeoCommands.GeoLocation<String> location1 = new RedisGeoCommands.GeoLocation<>("Shanghai", new Point(121.47, 31.23)); RedisGeoCommands.GeoLocation<String> location2 = new RedisGeoCommands.GeoLocation<>("Beijing", new Point(116.40, 39.90)); RedisGeoCommands.GeoLocation<String> location3 = new RedisGeoCommands.GeoLocation<>("Guangzhou", new Point(113.23, 23.16)); List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>(); locations.add(location1); locations.add(location2); locations.add(location3); redisTemplate.opsForGeo().add("china", locations); ``` 2. 获取地理位置信息 ```java Distance distance = redisTemplate.opsForGeo().distance("china", "Shanghai", "Beijing", RedisGeoCommands.DistanceUnit.KILOMETERS); System.out.println(distance.getValue() + distance.getUnit()); ``` 3. 查询指定范围内的地理位置信息 ```java Circle circle = new Circle(new Point(116.40, 39.90), new Distance(500, RedisGeoCommands.DistanceUnit.KILOMETERS)); GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().radius("china", circle); for (GeoResult<RedisGeoCommands.GeoLocation<String>> result : results) { System.out.println(result.getContent().getName() + " " + result.getDistance().getValue() + result.getDistance().getUnit()); } ``` 4. 查询指定地理位置与其他地理位置的距离 ```java Distance distance = redisTemplate.opsForGeo().distance("china", "Shanghai", "Guangzhou", RedisGeoCommands.DistanceUnit.KILOMETERS); System.out.println(distance.getValue() + distance.getUnit()); ``` 5. 查询指定地理位置的经纬度坐标 ```java List<Point> points = redisTemplate.opsForGeo().position("china", "Beijing", "Shanghai", "Guangzhou"); for (Point point : points) { System.out.println(point.getX() + "," + point.getY()); } ``` 希望这些示例可以帮助你更好地使用RedisTemplate执行GEO命令。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值