사붐이개발일기

mongoDB 4일차 (공간정보 GeoJSON) 본문

Database/MongoDB

mongoDB 4일차 (공간정보 GeoJSON)

sabeom 2023. 2. 8. 14:39

GeoJSON 객체

  • 공간 정보 쿼리의 유형: 교차(intersect), 포함(within), 근접(nearness)
    • GeoJSON: JSON 형태로 지형 데이터를 정의하는 포맷
      • <field>: { type: <GeoJSON type>, coordinates: <coordinates> }
      • type: Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection이 있음
      • coordinates: 좌표
  • 공간 정보 쿼리
    • 공간정보 쿼리를 효율적으로 실행
    • 공간정보 쿼리의 유형
      • $geoIntersects: 주어진 영역과 문서들의 영역에 교집합을 찾아서 반환
        • 입력값으로 GeoJSON 객체 허용
      • $geoWithin: 영역 안에 포함된 document들 반환
        • 입력값으로 폴리곤 계열의 GeoJSON객체, 레거시 좌표로 정의된 Shape도 허용
      • $nearSphere: 영역 안에 포함된 문서들을 가까운 순서대로 정렬해서 반환
        • GeoJSON을 이용할 때는 2dsphere 인덱스를, 레거시 좌표점을 이용할 때는 2d 인덱스를 사용

공간정보 쿼리 예제

  • 샘플 데이터 준비
    • places 컬렉션: GeoJSON 형태로 입력, legacyplaces 커렉션: 좌표계로 입력
db.places.insertOne({ name: "제주커피박물관 Baum", location:{ type:"Point", 
coordinates: [126.8990639, 33.4397954 ] } })
db.places.insertOne({ name: '신산리 마을카페', location: { type: 'Point',
coordinates: [126.8759347, 33.3765812 ] } })
db.legacyplaces.insertOne({ name: '제주커피박물관 Baum', location: 
[126.8990639, 33.4397954 ] })
db.legacyplaces.insertOne({ name: '신산리 마을카페', location:
[126.8759347, 33.3765812 ] })
  • $geoIntersects: 특정 위치가 특정 영역에 포함되는 경우의 도큐먼트를 결과로 출력
    • 구형 기하학(spherical geometry)을 이용 → 공간정보 인덱스를 사용할거라면 2dsphere를 선택
// ex) 신산리 안에있는 장소 찾기
db.places.find({
    location:{
        $geoIntersects: {
            $geometry: {
                type: 'Polygon', 
                coordinates: [
                    [[126.86, 33.39], [126.88, 33.39], [126.88, 33.37], [126.86, 33.37], [126.86, 33.39]]
                ]
            }
        }
    }
})
  • $geoWithin: 요청하는 영역안에 포함된 문서들을 반환
// 기본문법 1
{ <location field>: { 
    $geoWithin: { 
        $geometry: { 
            type: "<GeoJSON 오브젝트 타입>", 
            coordinates: [<coordinates>]
        }
    }
} }

// 기본문법 2
{ <location field>: {
	$geoWithin: {<shape operator>: <coordinates> }
} }
// ex) 신산리 마을회관 5km 내에 있는 장소 찾기
db.legacyplaces.find({
	location: {
    	$geoWithin: {
        	$centerSphere: [[126.876933, 33.381018], 5/6378.1]
        }	
    }
})
  • $near$nearSphere
    • 영역 안에 포함된 document들을 반환 (거리순으로 정렬 가능)
    • 특정 위치에서 가까운 곳을 검색할 수 있음
// 기본 문법 1
{
	<location field>: {
    	$nearSphere: {
        	$geometry: {
            	type: "Point", 
                coordinates: [<longitude>, <latitude>]
            }, 
            $minDistance: <distance in meters>, 
            $maxDistance: <distance in meters>
        }
    }
}


// 기본 문법 2
{
	<location field>: {
    	$nearSphere: [<x>, <y>], 
        $minDistance: <distance in meters>, 
        $maxDistance: <distance in meters>
    }
}
// ex) 성산일출봉에서 12km이내의 카페들을 가까운 순서대로 찾기

db.places.createIndex({"location": "2dsphere"})	// $nearSphere를 사용하기위해선 인덱스가 필요함
db.places.find({
	location: {
    	$nearSphere: {	// 인덱스필요
        	$geometry: {
            	type: "Point", 
                coordinates: [126.941131, 33.459216]
            }, 
            $minDistance: 1000, 
            $maxDistance: 12000
        }
    }
})