본문 바로가기

Database/mongoDB

MongoDB - Geospatial Queries (지리공간 쿼리)

 

※ MongoDB 공식 매뉴얼에 나와있는 Geospatial Queries 에 대한 내용을 허접하게나마 번역해 보도록 하겠습니다. 번역을 안하는게 나을 것 같은 용어들은 한번만 번역하거나 그대로 두었습니다.

 

 

MongoDB 는 geospatial data 에 대한 쿼리 연산을 지원합니다. 이 섹션은 MongoDB 의 geospatial 기능들에 대해 소개합니다.

Geospatial Data (지리공간 데이터)

MongoDB 에선, GeoJSON 객체나 legacy coordinates pairs (레거시 좌표 쌍) 로 geospatial data 를 저장할 수 있습니다.

GeoJSON Objects (GeoJSON 객체)

지구와 같은 구 위에서 geometry 를 계산하기 위해선, 위치 데이터를 GeoJSON 객체 형태로 저장해야 합니다.

GeoJSON data 를 명시하기 위해, 아래와 같은 조건과 함께 embedded document 를 사용해야 합니다.

  • type 필드엔 GeoJSON object type (Point, Polygon, MultiPoint 등등..) 을 명시합니다.
  • coordinates 필드엔 객체의 좌표를 명시합니다. 만약 위도와 경도 좌표를 지정하는 경우엔 [경도, 위도] 의 순서가 맞습니다.
    • 경도 값 범위는 -180 <= x <= 180 입니다. ( 0 : 그리니치 천문대(런던),  - : 서쪽, + : 동쪽 )
    • 위도 값 범위는 -90 <= y <= 90 입니다. ( 0 : 적도, -90 : 남극, +90 : 북극 )
<field>: { type: <GeoJSON type> , coordinates: <coordinates> }

 

예를들어 GeoJSON Point 를 명시한다면 아래와 같습니다.

 

location: {
      type: "Point",
      coordinates: [-73.856077, 40.848447]
}

 

MongoDB 에서 지원하는 GeoJSON 객체 목록과 예시는 GeoJSON objects 에서 볼 수 있습니다.

MongoDB 의 GeoJSON 객체에 대한 geospatial queries 는 구에서 계산됩니다; MongoDB 의 geospatial queries 는 WGS84 참조 시스템을 사용합니다.

 

Legacy Coordinate Pairs (레거시 좌표 쌍)

Euclidean plane (유클리드 평면) 상에서 거리를 계산하기 위해선 위치 데이터를 legacy coordinate paris 로 저장하고 2d index 를 사용해야 합니다. MongoDB 는 데이터를 GeoJSON Point 타입으로 변환하여 2dsphere index 를 통해 legacy coordinate paris 에서 구면 계산을 지원합니다.

데이터를 legacy coordinate paris 로 명시하는 방법에는 배열을 사용하거나 embedded document 를 사용 할 수 있습니다. (배열 사용을 추천)

 

배열을 통한 명시 (추천):

 

<field>: [ <x>, <y> ]

 

만약 위도와 경도 좌표를 명시한다면, 경도를 먼저 쓰고 위도를 그다음에 작성합니다.

 

<field>: [<longitude>, <latitude> ]

 

  • 경도 값 범위는 -180 ~ 180
  • 위도 값 범위는 -90 ~ 90

embedded document 를 통한 명시:

 

<field>: { <field1>: <x>, <field2>: <y> }

 

만약 위도와 경도 좌표를 명시한다면, 첫번째 필드에는 필드 이름에 상관없이 경도 값을, 두번째 필드에 위도 값을 넣어야 합니다.

 

<field>: { <field1>: <longitude>, <field2>: <latitude> }

 

  • 경도 값 범위는 -180 ~ 180
  • 위도 값 범위는 -90 ~ 90

legacy coordinate pairs 를 명시하는 두가지 방법중에서, embedded document 를 통한 방법은 몇몇 언어에선 associative map ordering 이 보장되지 않습니다. 따라서 배열을 통한 방법을 추천합니다.

 

Geospatial Indexes (지리공간 인덱스)

MongoDB 는 geospatial queries 를 지원하기 위해 다음과 같은 geospatial index 타입들을 제공합니다.

2dsphere

2dsphere index 는 지구와 같은 구에서 geometry 를 계산하는 쿼리들을 지원합니다.

2dsphere index 를 생성하기 위해선, db.collection.createIndex() 함수를 사용하고 인덱스 타입에 "2dsphere" 라고 명시해야 합니다 :

 

db.collection.createIndex( { <location field> : "2dsphere" } )

 

<location field> 는 GeoJSON 객체 혹은 legacy coordinate paris 를 값으로 가질 수 있는 필드입니다.

2dsphere index 에 대한 정보는 2dsphere Indexes 에서 볼 수 있습니다.

2d

2d index 는 2차원 평면상에서의 geometry 를 계산하는 쿼리를 지원합니다. 비록 이 인덱스가 구체 상에서 계산하는 쿼리인 $nearSphere 를 지원 가능하지만, 구와 관련된 쿼리 사용시에는 2dsphere index 를 사용하는게 좋습니다.

2d index 를 생성하기 위해선, db.collection.createIndex() 함수를 사용하고, 인덱스 타입에 "2d" 라고 명시해야 합니다 :

 

db.collection.createIndex( { <location field> : "2d" } )

 

<location field> 는 legacy coordinate paris 를 값으로 갖는 필드입니다.

관련된 더 많은 정보는 2d Indexes 에서 볼 수 있습니다.

Geospatial Indexes and Sharded Collections (지리공간 인덱스와 샤딩된 콜렉션)

콜렉션을 샤딩할 때 geospatial index 를 샤드키 로 사용할 수 없습니다. 그러나 샤드키가 아닌 다른 필드를 사용해 샤딩된 콜렉션에 geospatial index 를 생성할 수 있습니다.

다음과 같은 geospatial 연산들은 샤딩된 콜렉션에서 지원됩니다.

 

MongoDB 4.0 부터 $near / $nearSphere 쿼리가 샤딩된 콜렉션에서 지원됩니다. 4.0 이전 버전에서는 해당 쿼리들이 지원되지 않습니다. 대신 샤드 클러스터 용으로 $geoNear aggregation stage 혹은 geoNear command 를 사용해야 합니다. (4.0 & 이하 버전에서 사용 가능)

또한 $geoWithin / $geoIntersect 를 이용해 샤드 클러스터에 대한 geospatial data 를 쿼리할 수 있습니다.

Covered Queries

Geospatial indexes 는 covered query 가 될 수 없습니다. (covered query ? : 쿼리의 조건이나 프로젝션이 인덱스된 필드만 포함해서 다른 document 를 스캔하거나 가져올 필요가 없는 쿼리) 

Geospatial Queries (지리공간 쿼리)

NOTE

구체에 대한 쿼리에는 2dsphere index 결과값을 사용하세요.

양극을 감싸는 구형에 대한 쿼리에 2d index 를 사용하는 것은 잘못된 결과값이 나올 수 있습니다.

Geospatial Query Operators (지리공간 쿼리 연산자)

MongoDB 는 아래와 같은 geospatial query 연산자들을 지원합니다 :

 

Name Description
$geoIntersects GeoJSON geometry 와 교차하는 geometries 를 선택합니다. 2dsphere index 는 $geoIntersects 를 지원합니다.
$geoWithin GeoJSON geometry 안에 속하는 geometries 를 선택합니다. 2dsphere index 와 2d index 모두 $geoWithin 을 지원합니다.
$near 점과 가까운 순서의 geospatial objects 를 반환합니다. geospatial index 가 필요하며 2dsphere index 와 2d index 모두 $near 를 지원합니다.
$nearSphere 구체에서 점과 가까운 순서의 geospatial objects 를 반환합니다. geospatial index 가 필요하며 2dsphere index 와 2d index 모두 $nearSphere 를 지원합니다.

 

더 많은 내용과 예시들은 개별 참조 페이지에서 볼 수 있습니다. ($geoIntersects / $geoWithin / $near / $nearSphere)

Geospatial Aggregation Stage

MongoDB 는 아래와 같은 geospatial aggregation pipeline stage 를 지원합니다 :

 

Stage Description
$geoNear

geospatial point 와의 가까움 정도에 의해 정렬된 documents stream 을 반환합니다. geospatial data 에 대한 $match / $sort / $limit 기능을 통합합니다. 반환된 documents 는 추가된 distance 필드가 포함되어있으며 위치 식별자 필드를 포함할 수도 있습니다.

$geoNear 은 geospatial index 가 필요합니다.

 

더 많은 내용과 예시들은 $geoNear 참조 페이지에서 볼 수 있습니다.

Geospatial Models

MongoDB 의 geospatial query 는 구체 혹은 평평한 표면에서의 geometry 를 해석할 수 있습니다.

 

2dsphere index 는 구체에 대한 쿼리 (구체 표면의 geometry 를 해석하는 쿼리) 만 지원합니다.

 

2d index 는 flat 쿼리 (평평한 표면에서의 geometry 를 해석하는 쿼리) 와 몇몇 구체에 대한 쿼리를 지원합니다.

2d index 가 몇몇 구체에 대한 쿼리를 지원하긴 하지만, 그렇게 사용한 결과값에는 에러가 있을수 있습니다. 가능하면 구체에 대한 쿼리에는 2dsphere index 를 사용하세요.

 

아래 표는 각 geospatial 연산에서 사용되는 geospatial query 연산자들 (지원되는 쿼리) 을 나열합니다 :

 

Operation Spherical/Flat Query Notes
$near (GeoJSON point, 2dsphere index) Spherical GeoJSON 과 2dsphere index 를 함께 사용할 때 동일한 기능을 제공하는 $nearSphere 연산자도 보십시오
$near (legacy coordinates, 2d index) Flat  
$nearSphere (GeoJSON point, 2dsphere index) Spherical GeoJSON point 와 2dsphere index 를 사용하는 $near 연산자와 동일한 기능을 제공합니다
$nearSphere (legacy coordinates, 2d index) Spherical 대신 GeoJSON point 를 사용하세요
$geoWithin: {$geometry: ...} Spherical  
$geoWithin: {$box: ...} Flat  
$geoWithin: {$polygon: ...} Flat  
$geoWithin: {$center: ...} Flat  
$geoWithin: {$centerSphere: ...} Spherical  
Operation Spherical/Flat Query Notes
$geoIntersects Spherical  
$geoNear aggregation stage (2dsphere index) Spherical  
$geoNear aggregation stage (2d index) Flat  

Example

다음의 documents 를 사용하여 places 라는 이름의 collection 을 생성합니다 :

 

db.places.insert( {
    name: "Central Park",
   location: { type: "Point", coordinates: [ -73.97, 40.77 ] },
   category: "Parks"
} );
db.places.insert( {
   name: "Sara D. Roosevelt Park",
   location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] },
   category: "Parks"
} );
db.places.insert( {
   name: "Polo Grounds",
   location: { type: "Point", coordinates: [ -73.9375, 40.8303 ] },
   category: "Stadiums"
} );

 

다음 연산은 location 필드에 2dsphere index 를 생성합니다 :

 

db.places.createIndex( { location: "2dsphere" } )

 

$near 연산자를 사용한 다음의 쿼리는 명시된 GeoJSON point 로부터 1000 미터 이상 5000 미터 이하의 documents 를 가장 가까운 것부터 가장 먼 순서로 정렬해 반환합니다 :

 

db.places.find(
   {
     location:
       { $near:
          {
            $geometry: { type: "Point",  coordinates: [ -73.9667, 40.78 ] },
            $minDistance: 1000,
            $maxDistance: 5000
          }
       }
   }
)

 

다음의 geoNear aggregation operation 은 { category: "Parks" } 조건에 맞는 documents 를 명시된 GeoJSON point 로부터 가장 가까운 것부터 가장 먼 순서로 정렬해 반환합니다 :

 

db.places.aggregate( [
   {
      $geoNear: {
         near: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
         spherical: true,
         query: { category: "Parks" },
         distanceField: "calcDistance"
      }
   }
] )

 

출처 : https://docs.mongodb.com/manual/geospatial-queries/

 

Geospatial Queries — MongoDB Manual

Geospatial Queries MongoDB supports query operations on geospatial data. This section introduces MongoDB’s geospatial features. Geospatial Data In MongoDB, you can store geospatial data as GeoJSON objects or as legacy coordinate pairs. GeoJSON Objects To c

docs.mongodb.com

 

'Database > mongoDB' 카테고리의 다른 글

$geoWithin  (0) 2020.03.31
$geoIntersects  (0) 2020.03.25
Geospatial Query Operators (Geospatial 쿼리 연산자)  (0) 2020.03.25
GeoJSON Objects (GeoJSON 객체)  (0) 2020.03.18
MongoDB - Find Restaurants with Geospatial Queries  (0) 2020.03.10