본문 바로가기
NoSQL

MongoDB - Geospatial data

by Mi.Ro 2023. 8. 8.

Geospatial data

GeoJSON

  • type : GeoJSON type을 결정하는 key
  • coordinates : [longitude, lattitude]의 array
  • GeoJSON 예: loc : {type: "Point", coordinates: [100.1, 10.1]}

Legacy coordinate pairs

  • array나 embedded document로 저장
  • array 예 : loc : [100.1, 10.1]
  • embedded document 예 : loc : {'long' : 100.1, 'lati' : 10.1}
  • logitude(경도) : [-180,180] range (degrees)
  • lattitude(위도) : [-90,90] range (degrees)

GeoJSON Objects

  • 다양한 geometry type 지원 : point, linestring, polygon, multipoint, multistring, multipolygon
  • 예 : {geometry : {type : "Multipoint", coordinates : [ [100.1, 10.1], [110.1, 11.1]]}
  • circle이나 rectangle은 지원하지 않음

GeoJSON Lines

  • linestring : 2+ points의 array
  • 예 : {loc : {"type" : "LineString", "coordinates" : [1,5], [4,10], [3,12]}} -> point 3개로 선분 2개 표현
  • lineRing : 4+ points의 array로 closed lineString(첫번째 point가 마지막 point와 같음)
  • 예 : {loc : {"type" : "LineRing", "coordinates" : [1,5], [4,10], [3,12], [1,5]}}  -> point 3개로 삼각형 표현

GeoJSON polygons

  • polygon : rineRing array의 array로 표현
  • 예 : {loc : {"type" : "Polygon", "coordinates" :[ [[1,5], [4,10], [3,12], [1,5]], [[2,5], [7,8], [10,11], [2,5]] ]}}
  • 첫번째 linering은 나머지를 포함하고 반시계방향, 두번째부터는 시계방향이어야 함

Geospatial Queries

Geospatial query 종류

  • $geoWithin, $geoIntersects, $near...
  • $geoWithin : Range query. $box, $polygon specifier사용 가능, $geometry로 range query 사용

     > db.a.find({'address.coord' : {$geoWithin : {$box : [[ -73.9, 40.5 ], [ -73.3, 40.7 ]]}}})  -> $box 사용. bottom left와 top right corner 지정

     > db.a.find({'address.coord' : {$geoWithin : {$polygon : [[ -73.9, 40.5 ], [ -73.7, 40.5 ], [ -73.7, 40.7 ], [ -73.9, 40.7 ],
[ -73.9, 40.5 ]]}}})  -> $polygon 사용

     > db.a.find({'address.coord' : {$geoWithin : {$geometry : {type : 'polygon', coordinates : [[[ -73.9, 40.5 ], [ -73.7, 40.5 ], [ -73.7, 40.7 ], [ -73.9, 40.7 ], [ -73.9, 40.5 ]]]}}})  -> $geometry 사용

  • $geoIntersects : intersection query. $box, $polygon 사용 불가

     > db.a.find({'address.coord' : {$geoIntersects : {$geometry : {type : 'polygon', coordinates : [[[ -73.9, 40.5 ], [ -73.7, 40.5 ], [ -73.7, 40.7 ], [ -73.9, 40.7 ], [ -73.9, 40.5 ]]]}}})  -> $geometry 사용

Circular range queries

  • $center : GeoJSON은 circle을 지원히지 않음. center로부터의 range에 해당하는 영역 찾을때 $center specifier를 사용함. 거리 단위는 degree로, km 환산시 111.1로 나눠줌. flat geometry 사용해서 계산함

     > db.a.find({'address.coord' : {$geoWithin : {$center : [[ -73.9, 40.5 ], 2 / 111.1]}}}) -> 중심부터 2km range의 영역 검색.

  • $centerSphere : spherical geometry 사용. 단위는 radian으로, km 환산시 6378.1로 나눠줌

     > db.a.find({'address.coord' : {$geoWithin : {$centerSphere : [[ -73.9, 40.5 ], 2 / 6378.1]}}}) -> 중심부터 2km range의 영역 검색. $center를 썼을때와 geometry가 달라서 약간 결과가 다르게 나옴

Nearest neighbor queries

  • $near : center에서 가까운 것부터 지정 거리까지 targe을 찾아줌.(range+sort) legacy 좌표 사용시 2d type의 geospatial index가 필요함. flat geometry로 계산

     > db.a.createIndex({'address.coord' : '2d'})  -> 2d index가 반드시 필요함

     > db.a.find({'address.coord' : {$near : [ -73.9, 40.5 ], $maxDistance : 2 / 111.1}}) -> 중심부터 2km range의 nn 영역 검색. 가까운 순서대로 나오기 때문에 circular range query와 같은 결과에 순서가 다름

  • $near : GeoJSON에 사용할 때, 2dsphere type의 geospatial index가 필요함. 거리 단위가 m이므로 *1000으로 km 환산. spherical geometry로 계산

     > db.a.createIndex({'address.coord' : '2dsphere'})  -> 2dsphere index가 반드시 필요함. 

     > db.a.find({'address.coord' : {$near : {$geometry : {type : 'Point', coordinates : [ -73.9, 40.5 ]}, $maxDistance : 2000}}}) -> spherical geometry로 legacy 좌표를 썼을때와 결과가 다름

  • $nearSphere : spherical geometry 사용. legacy 좌표 사용시 단위는 radian. index는 2d, 2dsphere 모두 사용

     > db.a.createIndex({'address.coord' : '2d'})  or  db.a.createIndex({'address.coord' : '2dsphere'})

     > db.a.find({'address.coord' : {$nearSphere : [ -73.9, 40.5 ], $maxDistance : 2 / 6378.1}})

  • $nearSphere : GeoJSON에서 사용할 때 단위는 meter. index는 2dsphere 사용

     > db.a.createIndex({'address.coord' : '2dsphere'})  -> 2dsphere index가 반드시 필요함.

     > db.a.find({'address.coord' : {$nearSphere : {$geometry : {type : 'Point', coordinates : [ -73.9, 40.5 ]}, $maxDistance : 2000}}}) 

Query type operator center coordinates index type geometry distance unit
Circular range
($geoWithin)
$center legacy     degrees
$centerSphere legacy     radians
Nearest Neighbor $near legacy 2d flat degrees
GeoJSON 2dsphere spherical meters
$nearSphere legacy 2d/2dsphere spherical radians
GeoJSON 2dsphere spherical meters

'NoSQL' 카테고리의 다른 글

MongoDB - Aggregation  (0) 2023.08.09
MongoDB - text search  (0) 2023.08.08
MongoDB - Indexing  (0) 2023.08.07
MongoDB - Querying  (0) 2023.08.07
MongoDB - Crud operations  (0) 2023.08.07