Jedis 操作 Geospatial(地理空间)

在 Redis 的 3.2 版本中加入了地理空间(geospatial)以及索引半径查询的功能,这在需要地理位置功能的应用上或许可以一展身手。

Redis 的地理空间(geospatial)索引允许您存储地理坐标(经纬度)并搜索它们,此数据结构可用于查找给定半径或边界框内的邻近点。本文将介绍怎样通过 jedis 库操作 Redis 的 GeoSpatial 数据类型。

添加坐标

将指定的一个或多个地理位置元素添加 key 中,方法定义如下:

  • Long geoadd(String key, double longitude, double latitude, String member)

  • Long geoadd(String key, GeoAddParams params, Map<String,GeoCoordinate> memberCoordinateMap)

  • Long geoadd(String key, Map<String,GeoCoordinate> memberCoordinateMap)

示例:

// 北京市   116.404188,39.914687
// 天津市   117.225913,39.020948
// 成都市   104.071846,30.58706
// 添加一个点到 mykey 键
jedis.geoadd("mykey", 116.404188, 39.914687, "北京市");

// 一次添加多个点到 mykey 键
Map<String, GeoCoordinate> map = new HashMap<>();
map.put("天津市", new GeoCoordinate(117.225913, 39.020948));
map.put("成都市", new GeoCoordinate(104.071846, 30.58706));
jedis.geoadd("mykey", map);

计算距离

用来计算指定的两个位置之间的距离,方法定义如下:

  • Double geodist(String key, String member1, String member2)

  • Double geodist(String key, String member1, String member2, GeoUnit unit)

注意,GeoUnit 用来指定返回距离的单位,取值为 GeoUnit.FT、GeoUnit.KM、GeoUnit.M 和 GeoUnit.MI。

示例:

// 准备数据
Map<String, GeoCoordinate> map = new HashMap<>();
map.put("天津市", new GeoCoordinate(117.225913, 39.020948));
map.put("成都市", new GeoCoordinate(104.071846, 30.58706));
jedis.geoadd("mykey", map);

// 计算成都市和天津市之间的距离
Double dist = jedis.geodist("mykey", "成都市", "天津市");
System.out.println("相距:" + dist); // 相距:1521428.5819

// 使用指定的单位计算成都市和天津市之间的距离
dist = jedis.geodist("mykey", "成都市", "天津市", GeoUnit.KM);
System.out.println("相距:" + dist + "KM"); // 相距:1521.4286KM

GeoHash表示

用来返回一个或多个位置元素的 Geohash 表示,Geohash 是一种经纬度散列算法。方法定义如下:

  • List<String> geohash(String key, String... members)

示例:

// 准备数据
Map<String, GeoCoordinate> map = new HashMap<>();
map.put("天津市", new GeoCoordinate(117.225913, 39.020948));
map.put("成都市", new GeoCoordinate(104.071846, 30.58706));
jedis.geoadd("mykey", map);

// 获取 “天津市” 和 “成都市” 的 Geohash 值
List<String> geohashList = jedis.geohash("mykey", "成都市", "天津市");
System.out.println(Arrays.toString(geohashList.toArray()));
// [wm6n00ny9c0, wwgmgx939b0]

获取经纬度

用来返回一个或多个位置的经纬度信息,由于采用了 geohash 算法,返回的经纬度和添加时的数据可能会有细小误差。方法定义如下:

  • List<GeoCoordinate> geopos(String key, String... members)

示例:

// 准备数据
Map<String, GeoCoordinate> map = new HashMap<>();
map.put("天津市", new GeoCoordinate(117.225913, 39.020948));
map.put("成都市", new GeoCoordinate(104.071846, 30.58706));
jedis.geoadd("mykey", map);

// 获取 “成都市” 和 “天津市” 的经纬度信息
List<GeoCoordinate> geoCoordinateList = jedis.geopos("mykey", "天津市", "成都市");
for(GeoCoordinate geoCoordinate : geoCoordinateList) {
   System.out.println("经度:" + geoCoordinate.getLongitude() + " 纬度:" + geoCoordinate.getLatitude());
}
// 结果:
// 经度:117.22591549158096 纬度:39.02094865472754
// 经度:104.0718474984169 纬度:30.58705941352803

位置搜索

用来搜索以给定位置为中心,半径不超过给定半径的附近所有位置。方法定义如下:

  • List<GeoRadiusResponse> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit)

  • List<GeoRadiusResponse> georadius(String key, double longitude, double latitude, double radius, GeoUnit unit, GeoRadiusParam param)

  • List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius, GeoUnit unit)

  • List<GeoRadiusResponse> georadiusByMember(String key, String member, double radius, GeoUnit unit, GeoRadiusParam param)

示例1:使用指定的经纬度搜索附近的位置,如下:

// 准备数据
Map<String, GeoCoordinate> map = new HashMap<>();
map.put("天津市", new GeoCoordinate(117.225913, 39.020948));
map.put("成都市", new GeoCoordinate(104.071846, 30.58706));
map.put("北京市", new GeoCoordinate(116.404188, 39.914687));
jedis.geoadd("mykey", map);

// 获取 “北京市” 周边 1000km 范围内的点
List<GeoRadiusResponse> list = jedis.georadius("mykey", 116.404188, 39.914687, 1000, GeoUnit.KM);
for(GeoRadiusResponse geoRadiusResponse : list) {
   System.out.println(geoRadiusResponse.getMemberByString());
}
// 结果:
// 天津市
// 北京市

// 获取 “北京市” 周边 1000km 范围内的点,以及点的经纬度
GeoRadiusParam geoRadiusParam = new GeoRadiusParam();
geoRadiusParam.withCoord(); // 指示同时返回匹配项的经度、纬度坐标
list = jedis.georadius("mykey", 116.404188, 39.914687, 1000, GeoUnit.KM, geoRadiusParam);
for(GeoRadiusResponse geoRadiusResponse : list) {
   GeoCoordinate geoCoordinate = geoRadiusResponse.getCoordinate();
   System.out.println(geoRadiusResponse.getMemberByString() +
           " 经度:" + geoCoordinate.getLongitude() + " 纬度:" + geoCoordinate.getLatitude());
}
// 结果:
// 天津市 经度:117.22591549158096 纬度:39.02094865472754
// 北京市 经度:116.40418857336044 纬度:39.91468626606813

示例2:使用指定的成员搜索成员附近的位置,如下:

// 准备数据
Map<String, GeoCoordinate> map = new HashMap<>();
map.put("天津市", new GeoCoordinate(117.225913, 39.020948));
map.put("成都市", new GeoCoordinate(104.071846, 30.58706));
map.put("北京市", new GeoCoordinate(116.404188, 39.914687));
jedis.geoadd("mykey", map);

// 获取 “北京市” 周边 1000km 范围内的点,以及点的经纬度
GeoRadiusParam geoRadiusParam = new GeoRadiusParam();
geoRadiusParam.withCoord(); // 指示同时返回匹配项的经度、纬度坐标
List<GeoRadiusResponse> list = jedis.georadiusByMember("mykey", "北京市", 1000, GeoUnit.KM, geoRadiusParam);
for(GeoRadiusResponse geoRadiusResponse : list) {
   GeoCoordinate geoCoordinate = geoRadiusResponse.getCoordinate();
   System.out.println(geoRadiusResponse.getMemberByString() +
           " 经度:" + geoCoordinate.getLongitude() + " 纬度:" + geoCoordinate.getLatitude());
}
// 结果:
// 天津市 经度:117.22591549158096 纬度:39.02094865472754
// 北京市 经度:116.40418857336044 纬度:39.91468626606813
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号