位置相关操作
GEO数据结构
GEO就是Geolocation的简写形式,代表地理坐标。
常见的命令有:
- GEOADD:添加一个地理空间信息,包含:经度(longitude)、纬度(latitude)、值(member)
- GEODIST:计算指定的两个点之间的距离并返回
- GEOHASH:将指定member的坐标转为hash字符串形式并返回
- GEOPOS:返回指定member的坐标
- GEOSEARCH:在指定范围内搜索member,并按照与指定点之间的距离排序后返回。范围可以是圆形或矩形。
- 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;
}