-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Geohash 기반의 Geo API 개발. #492
Comments
위 링크들을 참고해서 생각해본 spec은 다음과 같습니다.
GEO 명령
gop create (Geo Collection 생성)Geo collection을 empty 상태로 생성한다.
gop add (Geo Element 삽입)Geo collection에 하나의 field, element를 삽입한다.
gop update (Geo Element 변경)Geo collection에서 하나의 field에 대해 element 변경을 수행한다.
gop delete (Geo Element 삭제)Geo collection에서 하나 이상의 field 이름을 주어, 그에 해당하는 element를 삭제한다.
gop pos (Geo element에 대한 위도, 경도 조회)Geo collection에서 하나 이상의 field 이름을 주어, 그에 해당하는 위도 및 경도를 조회한다.
gop dist (두 Geo element 간의 거리 조회)Geo collection에서 두 개의 field 이름을 주어, 두 element 사이의 거리를 조회한다.
gop raditem (Geo element 근처에 있는 Geo element 조회)Geo collection에서 field 이름과 raidus 값을 주어, field에 해당하는 element에서 반경이내의 element를 조회한다.
gop radlocation (입력한 좌표 근처에 있는 Geo element 조회)Geo collection에서 하나 field이름과 radius
gop hash (Geo element의 해시값 조회)Geo collection에서 하나 이상의 field 이름을 주어, 그에 해당하는 element를 조회한다.
|
redis와 같이 sorted set을 구현하여 Geo API를 구현한다면, Geo를 map, list, set, btree와 같이 하나의 collection으로 보는 관점이 맞을까요? |
@HarryKim93 |
@HarryKim93
확인해 주시고, 다르게 생각하는 부분이 있으면 의견 공유 바랍니다. |
기존에는 RB-Tree를 사용해서 구현하려했는데, geohash 특성상 말씀하신대로 b+tree collection으로 하는 것이 여러 geo 값 스캔시 overhead가 더 적고, radius 연산 시 더 효율적일 것 같습니다.
네 맞습니다.
field 값의 길이를 제한하여, 위의 명령어로 통일하는 것은 어떨까요?
기존 b+collection의 확장기능으로 sorted set을 구현하는 방법으로 생각해보겠습니다. |
@HarryKim93
|
@HarryKim93
|
현재 명시된 기능 (pos, dist, radius) 외에는 지금 생각이 나지 않습니다. 이것도 한번 고민해보도록 하겠습니다.
네. 자유롭게 수행이 가능합니다. Geohash의 경우에는 Z-order curve와 base32를 사용해서 해싱했을 경우, Redis 코드를 통해서 예시로 보여드리자면 static inline uint64_t interleave64(uint32_t xlo, uint32_t ylo) {
static const uint64_t B[] = {0x5555555555555555ULL, 0x3333333333333333ULL,
0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
0x0000FFFF0000FFFFULL};
static const unsigned int S[] = {1, 2, 4, 8, 16};
uint64_t x = xlo;
uint64_t y = ylo;
x = (x | (x << S[4])) & B[4];
y = (y | (y << S[4])) & B[4];
x = (x | (x << S[3])) & B[3];
y = (y | (y << S[3])) & B[3];
x = (x | (x << S[2])) & B[2];
y = (y | (y << S[2])) & B[2];
x = (x | (x << S[1])) & B[1];
y = (y | (y << S[1])) & B[1];
x = (x | (x << S[0])) & B[0];
y = (y | (y << S[0])) & B[0];
return x | (y << 1);
} 하고 있고(interleave 후 4bit씩 base32의 값과 1:1대응 시켜 만든 문자열이 해시값) geohash에서 coordinate 변환 경우에는(decode) static inline uint64_t deinterleave64(uint64_t interleaved) {
static const uint64_t B[] = {0x5555555555555555ULL, 0x3333333333333333ULL,
0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL};
static const unsigned int S[] = {0, 1, 2, 4, 8, 16};
uint64_t x = interleaved;
uint64_t y = interleaved >> 1;
x = (x | (x >> S[0])) & B[0];
y = (y | (y >> S[0])) & B[0];
x = (x | (x >> S[1])) & B[1];
y = (y | (y >> S[1])) & B[1];
x = (x | (x >> S[2])) & B[2];
y = (y | (y >> S[2])) & B[2];
x = (x | (x >> S[3])) & B[3];
y = (y | (y >> S[3])) & B[3];
x = (x | (x >> S[4])) & B[4];
y = (y | (y >> S[4])) & B[4];
x = (x | (x >> S[5])) & B[5];
y = (y | (y >> S[5])) & B[5];
return x | (y << 32);
} 처럼 해싱된 값에대해 Z-curve 기법을 반대로 사용하여 위도와 경도를 구할 수 있습니다. |
@HarryKim93 변환 방식을 알려주어서 감사합니다. 1개 캐시 노드에서 point 기반의 위치 정보를 저장하고 dist, radius 연산을 수행하는 것은 대략 정리/이해가 된 것 같습니다. |
추가적인 의견입니다.
btree의 경우, skiplist의 경우, 최근에 고안된 자료구조이며
아래 표에 나와있는대로, geohash 길이에 따른 오차를 이용하면 될 것 같습니다. geohash 길이가 8로 설정되어 있는 조건에서
그러므로 radius 값에 따라서, |
@HarryKim93
|
ARCUS에서 GeoHash 기반의 GeoAPI를 개발한다.
참고 자료
The text was updated successfully, but these errors were encountered: