Skip to content

位置相关操作

GEO数据结构

GEO就是Geolocation的简写形式,代表地理坐标。

常见的命令有:

  1. GEOADD:添加一个地理空间信息,包含:经度(longitude)、纬度(latitude)、值(member)
  2. GEODIST:计算指定的两个点之间的距离并返回
  3. GEOHASH:将指定member的坐标转为hash字符串形式并返回
  4. GEOPOS:返回指定member的坐标
  5. GEOSEARCH:在指定范围内搜索member,并按照与指定点之间的距离排序后返回。范围可以是圆形或矩形。
  6. GEOSEARCHSTORE:与GEOSEARCH功能一致,不过可以把结果存储到一个指定的key。

与北京站之间的距离

向redis中添加北京站坐标

java
@Test
void test1() {
    // 北京站: 116.42803 39.903738
    double x = 116.42803;
    double y = 39.903738;
    String key = "RedisSessionDemo:geo";
    Long isSuccess = stringRedisTemplate.opsForGeo()
        .add(key, new Point(x, y), "beijingStation");
    System.out.println(isSuccess);
}

计算与北京站之间的距离

java
public Double getDistance(Double x, Double y) {
    String key = "RedisSessionDemo:geo";
    stringRedisTemplate.opsForGeo().add(key, new Point(x, y), "temp");
    Distance distance = stringRedisTemplate.opsForGeo()
        .distance(key, "temp", "beijingStation");
    stringRedisTemplate.opsForGeo().remove(key, "temp");
    if (distance == null) {
        return -1.0;
    }
    return distance.getValue();
}

查看附近的火车站

预先添加北京三个火车站坐标

java
@Test
void test3() {
    String key = "RedisSessionDemo:geo";
    // 北京站: 116.42803 39.903738
    stringRedisTemplate.opsForGeo()
        .add(key, new Point(116.42803, 39.903738), "北京站");
    // 北京南站: 116.378248 39.865275
    stringRedisTemplate.opsForGeo()
        .add(key, new Point(116.378248, 39.865275), "北京南站");
    // 北京西站: 116.322287 39.893729
    stringRedisTemplate.opsForGeo()
        .add(key, new Point(116.322287, 39.893729), "北京西站");
}

查询附近的火车站

java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GEODTO {
    String name;
    double distance;
}
java
@Override
public List<GEODTO> nearbyStation(Double x, Double y) {
    String key = "RedisSessionDemo:geo";
    stringRedisTemplate.opsForGeo().add(key, new Point(x, y), "temp");
    GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = stringRedisTemplate.opsForGeo().search(key, GeoReference.fromCoordinate(x, y), new Distance(100 * 1000), RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs().includeDistance());
    List<GEODTO> result = new ArrayList<>();
    if (geoResults != null) {
        geoResults.getContent().stream().skip(1).forEach(item -> {
            String name = item.getContent().getName();
            double distance = item.getDistance().getValue();
            result.add(new GEODTO(name, distance));
        });
    }
    return result;
}
image-20240201213817837

Released under the MIT License.