※ 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 연산들은 샤딩된 콜렉션에서 지원됩니다.
- $geoNear aggregation stage
- $near and $nearSphere query operators (starting in MongoDB 4.0)
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/
'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 |