Redis는 Geospatial 데이터를 사용하면 위치정보를 저장할 사용할 수 있다
Geospatial 자료구조는 sorted set의 확장이다
sorted set 형태로 데이터를 저장하는데
이때 내부적으로는 위도,경도를 geohash로 인코딩한 값을 저장하게 된다
Geohash란?
아래 사진 처럼 특정 위치(위,경도)를 문자열로 인코딩 하는 방식
지구를 평면 지도로 만들고 그것을
지구를 평면 지도로 만들고 그것을 나누어서 문자를 하나씩 맵핑해놓은것이다
중국부근이 w에 대응되고 그 w안에서 또 사각형으로 나누어서 문자들을 맵핑하고
이런식으로 쭉 나가는 것이다
그래서 서울은 wydm9가된다
https://geohash.softeng.co/ 여기서 확인 가능
저장
위치정보를 저장하게 되면
위 geohash가 sorted set의 score부분에 들어가게된다
Redis Cli에서는 GEOADD 명령어를 사용하여 key를 지정하고 경도, 위도, 이름을 저장할 수 있다
GEOADD location 126.823162 35.191378 "Vino Cafe"
만약 이런식으로 추가하게 되면
키는 'location' score는 위,경도데이터, member는 "Vino Cafe" 가 들어간다
저 위경도가 `wssdf7as` 이런 `geohash` 문자열로 바뀌고
이것이 정수형태로 또 변경되어서 `score`부분에 들어감
범위 검색
`GeoPatial`의 범위 검색하는 명령어는
`georadiusbymember`와 `georadius`가 있다
georadiusbymember : member를 기준으로 반경내의 다른 member검색
georadius : 입력된 위경도를 기준점으로 반경내의 다른 member검색
*이렇게 두개로 쓰던것 redis 6.2.0부터 `GEOSEARCH`로 통합되고 위의 것들은 deprecated되었다고 한다.
GEOSEARCH
georadiusbymember는 `FROMMEMBER`와 `BYRADIUS` 옵션을 통해서 사용가능
GEOSEARCH KEY FROMMEMBER "member" BYRADIUS 100 m [ASC | DESC]
GEOSEARCH location FROMMEMBER "Vino Cafe" BYRADIUS 100 m ASC
georadius는 `BYLONLAT`과 `BYRADIUS`옵션을 통해 사용 가능
GEOSEARCH locations BYLONLAT 127.0 37.5 BYRADIUS 100 km
spring에서의 사용
public List<String> findDriversWithLocation(Double latitude, Double longitude) {
String key = RedisKey.DRIVER_LOCATIONS;
Distance radius = new Distance(5, Metrics.KILOMETERS);
Circle circle = new Circle(new Point(longitude, latitude), radius);
GeoResults<RedisGeoCommands.GeoLocation<Object>> results = redisTemplate.opsForGeo()
.radius(key, circle);
List<String> driverIds = results.getContent().stream()
.map(result -> (String)result.getContent().getName())
.collect(Collectors.toList());
return driverIds;
}