몽고디비 공간 쿼리

개발 끄적끄적 .. ✍️·2021년 12월 21일
0

한 지점의 위/경도를 가져와 가까운 지점을 지도의 원하는 위치 찍으려고 한다. 과연 어떻게 가져와야할까 ?

몽고디비에는 공간과 관련한 쿼리가 존재한다. 단순히 해당 위/경도를 찾을 수도 있고, max distance를 설정하고 그 지점 안의 모든 좌표를 찾을 수도 있고, 가까운 곳을 찾을 수도 있다.

$near / $nearSphere

  • 기준점을 설정하고 해당 기준점에서 부터 가까운 점들을 정렬하여 찾아주는 공간 쿼리이다. ($nearSphere은 GeoJSON 객체에 대해서도 찾아준다고한다. 경험해보지 못함 ..)
  • 실제 좌표가 들어가는 coordinate는 list [경도, 위도]형식으로 들어간다
  • 해당 쿼리 연산자를 사용하려면 아래와 같이 작성하면 된다
    db.collection.find({ $near: {
      			$geometry: {
    				type: 'Point',
    				coordinates: [경도, 위도]
    				}
    			} 
    		})
  • 추가적으로 쿼리 개수를 설정하고자 한다면 find()메소드 뒤에 .limit(5) 와 같이 설정하여 pagination 등에 활용할 수 있다

$maxDistance / $minDistance

  • 기준점을 설정하고 해당 기준점으로 부터 일정 거리 이상/이하에 해당 되는 점을 조회한다
  • 해당 쿼리 연산자를 사용하려면 아래와 같이 작성하면 된다
    { $nearSphere: {
      		$geometry: {
                          type: 'Point',
                          coordinates: [경도, 위도]
                      },
      		$maxDistance: 미터,
                  } }

$geoWithin

  • $center, $box 등과 함께 혼합하여 사용함

$center

  • 중심 기준점을 설정하고 반지름이 반경인 원 안의 좌표를 찾는다.
    { $geoWithin: { $center: [[경도, 위도], 라디안] } }
  • 실제 $center 쿼리 연산자를 통해 한 지점에서 설정한 범위 내의 지역의 요약 값을 출력하는 api를 만들어 본적이 있다. (성능 문제로 다른 방식으로 변경했지만 ..!)

$box

  • $center가 반지름이 기준이라면 $box는 두 개의 리스트 (배열)을 받는데 배열의 첫번째는 정사각형의 좌하점의 경/위도이고 두번 째 배열의 우상점의 경/위도 이다.
    { $geoWithin: { $box: [[경도, 위도], [경도, 위도]] } }
  • 실제 지도 개발을 할 때 화면 크기에 맞게 범위 내의 좌표 정보를 가져오는데 아주 유용하게 사용했던 쿼리 연산자이다.

마무리

  • 몽고디비 공간 쿼리를 지도 개발을 통해 경험해보면서 느낀 점은 성능이 매우 강력하다는 것이다.
  • 실제 카카오 택시에서 몽고디비 공간 인덱스를 사용하여 사용자 위치를 검색을 최적화 하여 서비스를 제공한다고 한다.
  • 단순히 속도 뿐만 아니라 최대 거리, 근접 거리, 원, 박스형태 등의 다양한 공간을 측정할 수 있는 쿼리 연산자들이 존재하여 이를 잘 활용한다면 보다 많은 분야에서 사용될 수 있을 것 같다.

0개의 댓글