Redis在3.2版本里面新增的一个功能就是对GEO(地理位置)的支持。
地理位置大概提供了6个命令,分别为:
1.GEOADD
2.GEODIST
3.GEOHASH
4.GEOPOS
5.GEORADIUS
6.GEORADIUSBYMEMBER
这个功能在现在互联网行业用处还是很多的,比如:
附近的人,网约车,外卖….
试验了一下,感觉非常好用,记录下来
package com.redis.geo;
import com.redis.util.RedisUtil;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.GeoCoordinate;
import redis.clients.jedis.GeoRadiusResponse;
import redis.clients.jedis.GeoUnit;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.geo.GeoRadiusParam;
import java.util.List;
/** * Geo */
public class GeoTest {
/** * 向location中添加两个座标信息 */
@Test
public void geoAdd(){
Jedis jedis = RedisUtil.getJedis();
Long geoadd1 = jedis.geoadd("location", 121.377142, 31.180923, "local1");
System.out.println("返回结果:"+geoadd1);
Long geoadd2 = jedis.geoadd("location", 121.37686,31.176551, "local2");
System.out.println("返回结果:"+geoadd2);
Long geoadd3 = jedis.geoadd("location", 121.398156,31.180774, "local3");
System.out.println("返回结果:"+geoadd3);
Long geoadd4 = jedis.geoadd("location", 121.388814,31.187633, "local4");
System.out.println("返回结果:"+geoadd4);
Long geoadd5 = jedis.geoadd("location", 121.369698,31.180466, "local5");
System.out.println("返回结果:"+geoadd5);
Long geoadd6 = jedis.geoadd("location", 121.358775,31.177685, "local6");
System.out.println("返回结果:"+geoadd6);
Long geoadd7 = jedis.geoadd("location", 121.373148,31.16477, "local7");
System.out.println("返回结果:"+geoadd7);
Long geoadd8 = jedis.geoadd("location", 121.398444,31.167674, "local8");
System.out.println("返回结果:"+geoadd8);
Long geoadd9 = jedis.geoadd("location", 121.376885,31.203696, "local9");
System.out.println("返回结果:"+geoadd9);
Long geoadd10 = jedis.geoadd("location", 121.399306,31.186644, "local10");
System.out.println("返回结果:"+geoadd10);
Long geoadd11 = jedis.geoadd("location", 121.340665,31.169343, "local11");
System.out.println("返回结果:"+geoadd11);
}
/** * 返回两个给定位置之间的距离。如果两个位置之间的其中一个不存在, 那么命令返回空值。 * 指定单位的参数 unit 必须是以下单位的其中一个: * m 表示单位为米。 * km 表示单位为千米。 * mi 表示单位为英里。 * ft 表示单位为英尺。 */
@Test
public void geoDist(){
Jedis jedis = RedisUtil.getJedis();
Double geodist1 = jedis.geodist("location", "local1", "local2");
System.out.println("获取两点的直线距离,默认单位m:"+geodist1);
Double geodist2 = jedis.geodist("location", "local1", "local2", GeoUnit.M);
System.out.println("获取两点的直线距离,指定单位m:"+geodist2);
Double geodist3 = jedis.geodist("location", "local1", "local2", GeoUnit.KM);
System.out.println("获取两点的直线距离,指定单位km:"+geodist3);
}
/** * 从key里返回所有给定位置元素的位置(经度和纬度)。 * 返回值:GEOPOS 命令返回一个数组, 数组中的每个项都由两个元素组成: * 第一个元素为给定位置元素的经度, * 第二个元素则为给定位置元素的纬度。 * 当给定的位置元素不存在时, 对应的数组项为空值。 */
@Test
public void geoPos(){
Jedis jedis = RedisUtil.getJedis();
List<GeoCoordinate> geopos1 = jedis.geopos("location", "local1","local2","local3","local4","local5","local6","local7","local8","local9","local10","local11");
for (GeoCoordinate geopo : geopos1) {
System.out.println("经度:"+geopo.getLongitude());
System.out.println("纬度:"+geopo.getLatitude());
System.out.println("==========================");
}
}
/** * GEOHASH key member [member ...] * 命令描述:返回一个或多个位置元素的 Geohash 表示。 * 通常使用表示位置的元素使用不同的技术,使用Geohash位置52点整数编码。 * 由于编码和解码过程中所使用的初始最小和最大座标不同,编码的编码也不同于标准。此命令返回一个标准的Geohash * 返回值:一个数组, 数组的每个项都是一个 geohash 。 * 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。 */
@Test
public void geoHash(){
Jedis jedis = RedisUtil.getJedis();
List<String> geohash = jedis.geohash("location", "local1","local2","local3","local4","local5","local6","local7","local8","local9","local10","local11");
for (String s : geohash) {
System.out.println("geoHash值:"+s);
}
}
/** * 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。 * 范围可以使用以下其中一个单位: * m 表示单位为米。 * km 表示单位为千米。 * mi 表示单位为英里。 * ft 表示单位为英尺。 * 在给定以下可选项时, 命令会返回额外的信息: * * WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。 * WITHCOORD: 将位置元素的经度和维度也一并返回。 * WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。这个选项主要用于底层应用或者调试, 实际中的作用并不大。 * 命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式: * * ASC: 根据中心的位置, 按照从近到远的方式返回位置元素。 * DESC: 根据中心的位置, 按照从远到近的方式返回位置元素。 * 在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 * 虽然用户可以使用 COUNT <count> 选项去获取前 N 个匹配元素, * 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, * 即使只使用 COUNT 选项去获取少量元素, 命令的执行速度也可能会非常慢。 * 但是从另一方面来说, 使用 COUNT 选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。 * * 返回值: * 在没有给定任何 WITH 选项的情况下, 命令只会返回一个像 [“New York”,”Milan”,”Paris”] 这样的线性(linear)列表。 * 在指定了 WITHCOORD 、 WITHDIST 、 WITHHASH 等选项的情况下, 命令返回一个二层嵌套数组, 内层的每个子数组就表示一个元素。 * 在返回嵌套数组时, 子数组的第一个元素总是位置元素的名字。 至于额外的信息, 则会作为子数组的后续元素, 按照以下顺序被返回: * * 以浮点数格式返回的中心与位置元素之间的距离, 单位与用户指定范围时的单位一致。 * geohash 整数。 * 由两个元素组成的座标,分别为经度和纬度。 * * GeoRadiusParam使用的是链式写法: * 不加GeoRadiusParam.geoRadiusParam().withCoord()参数返回的coordinate为null * 不加GeoRadiusParam.geoRadiusParam().withDist()参数返回的distance为0 * 不加GeoRadiusParam.geoRadiusParam().sortAscending()或者sortDescending()参数返回值是不排序的(按照distance排序) */
@Test
public void geoRadius(){
Jedis jedis = RedisUtil.getJedis();
List<GeoRadiusResponse> location = jedis.georadius("location",121.375735,31.184914,1, GeoUnit.KM,GeoRadiusParam.geoRadiusParam().withCoord().withDist().sortDescending());
System.out.println("==指定范围内的数量为:"+location.size());
for (GeoRadiusResponse geoRadiusResponse : location) {
System.out.println("distance:"+geoRadiusResponse.getDistance());
System.out.println("coordinate:"+geoRadiusResponse.getCoordinate());
System.out.println("lon:"+geoRadiusResponse.getCoordinate().getLongitude());
System.out.println("lat:"+geoRadiusResponse.getCoordinate().getLatitude());
System.out.println("memberByString:"+geoRadiusResponse.getMemberByString());
System.out.println("==================================================");
}
}
/** * georadiusByMember方法与georadius类似,只不过这里指定的不是座标,而是member */
@Test
public void geoRadiusByMember(){
Jedis jedis = RedisUtil.getJedis();
List<GeoRadiusResponse> locations = jedis.georadiusByMember("location", "local2", 2, GeoUnit.KM,GeoRadiusParam.geoRadiusParam().withCoord().withDist());
System.out.println("==指定范围内的数量为:"+locations.size());
for (GeoRadiusResponse rr : locations) {
System.out.println("distance:"+rr.getDistance());
System.out.println("coordinate:"+rr.getCoordinate());
System.out.println("lon:"+rr.getCoordinate().getLongitude());
System.out.println("lat:"+rr.getCoordinate().getLatitude());
System.out.println("memberByString:"+rr.getMemberByString());
System.out.println("==================================================");
}
}
}