Skip to content

Instantly share code, notes, and snippets.

@hmmhmmhm
Created June 19, 2020 03:47
Show Gist options
  • Save hmmhmmhm/5b7bc60b4f6b0482714d366b0740a658 to your computer and use it in GitHub Desktop.
Save hmmhmmhm/5b7bc60b4f6b0482714d366b0740a658 to your computer and use it in GitHub Desktop.
Geohash 그룹핑 및 쿼리 방법 (가까운 위치의 정보 얻어올때)
import ngeohash from 'ngeohash'
import sortByDistance from 'sort-by-distance'
import { readFileSync } from 'fs'
export const geoQuery = async ({
x,
y,
rangeMeter = 70000, // 범위 (미터))
limit = 50, // 쿼리 결과물 갯수
memGeo,
key
})=> {
let queryItems = memGeo.nearBy(x, y, rangeMeter)
// GeoHash 를 위경도로 정정
for(let queryItemsIndex in queryItems){
let {g} = queryItems[queryItemsIndex]
let {latitude, longitude} = ngeohash.decode_int(g)
delete queryItems[queryItemsIndex].g
queryItems[queryItemsIndex].x = latitude
queryItems[queryItemsIndex].y = longitude
}
// 가까운 순으로 정렬
queryItems = sortByDistance({x, y}, queryItems)
// 거리 표현 교정
for(let queryItemsIndex in queryItems) {
// 떨어진 거리를 1m 단위로 조정
queryItems[queryItemsIndex].distance *= 100000
// 소수점 전부 삭제
queryItems[queryItemsIndex].distance =
Number(queryItems[queryItemsIndex].distance.toFixed(0))
if(queryItems[queryItemsIndex].distance < 1000){
// m 단위 표현 추가
queryItems[queryItemsIndex].distance =
`${queryItems[queryItemsIndex].distance}m`
} else{
// km 단위로 조정
queryItems[queryItemsIndex].distance /= 1000
// 소수점 2 글자만 허용
queryItems[queryItemsIndex].distance =
Number(queryItems[queryItemsIndex].distance.toFixed(2))
// m 단위 표현 추가
queryItems[queryItemsIndex].distance =
`${queryItems[queryItemsIndex].distance}km`
}
}
// 만약 갯수가 제한보다 많다면 크기조정
if(queryItems.length > limit) queryItems.length = limit
let results: any[] = []
for(let {i, x, y, distance} of queryItems){
try{
let dbItem = JSON.parse(String(readFileSync(`./static_json/place/${String(key).replace('%i%', i)}.json`)))
dbItem.queryTag = { i, x, y, distance }
results.push(dbItem)
}catch(e){}
}
return results
}
@hmmhmmhm
Copy link
Author

memGeo 구성방법

import { readFileSync, mkdirSync, writeFileSync, existsSync } from 'fs'
import Geo from 'geo-nearby'

// 좌표기반으로 검색 결과를 알려줘야하는 데이터는
// 즉각으로 검색한 결과를 리턴하게끔 메모리에 상시 올려놓게 구성합니다.
// 반복문에서 아래와 같은 정보 삽입
memcachedGeoIndexs.push([x, y, String(placeId)])
writeFileSync(`${STATIC_JSON_PATH}/memgeo-${id}.json`, JSON.stringify(Geo.createCompactSet(memcachedGeoIndexs)))
for(let supportType of supportTypes){
    if(types.indexOf(supportType) != -1){
        let memGeo = new Geo(
            JSON.parse(
                String(readFileSync(`./static_json/memgeo-${supportType}.json`))
            ),
            { sorted: true }
        )
        queryResults[`${supportType}`] = await geoQuery({...opts, memGeo})
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment