MongoDB
≡ 목차 (Table of Contents)
MongoDB 는 이름처럼 Database 시스템이다. 가장 큰 특징은 도큐먼트 기반 데이터베이스, 즉 고정된 스키마가 없는 동적인 데이터를 관리하는 데이터베이스다. 이로 인해 NoSQL DB 의 대명사이기도 하다.
CLI 사용법 메모
연결하기(Connect)
호스트 이름과 포트 번호를 이용해 접속할 때는 아래처럼 사용할 수 있다.
mongo --host foo.bar --port 27017
참고로 27017은 MongoDB 의 기본 포트다. 따라서 이 경우 생략해도 된다.
URI를 이용한 접속도 가능하다.
mongo mongodb://host.foo.bar:27017/dbname
dbname 은 생략할 수 있다.
명령어 노트
데이터베이스 선택(Select Database)
use
명령을 이용해 데이터베이스를 선택할 수 있다.
use dbname
데이터베이스 목록 보기(List Databases)
데이터베이스 이름이 기억나지 않아서 검색해야 될 때는 아래 커맨드를 사용할 수 있다.
db.adminCommand({listDatabases: 1})
왜 이런 중요한 커맨드를 따로 만들어 두지 않았는지 의문이다. 기억 안 나면 어떻게 찾으라는 건지 모르겠다.
컬렉션 조회(List Collections)
컬렉션 조회는 아래처럼 전용 명령어가 있다.
show collections
삽입(Insert)
db.collection.insert({key: value, ...})
데이터베이스에 지정된 도큐먼트를 삽입한다.
조회(Find or Query)
다른 DBMS에서는 쿼리라 부르는 것과 비슷한 검색 혹은 조회하는 기능은 find
명령을 사용한다.
db.colllection.find({key: value, ...})
좀 더 고급 검색 쿼리는 아래에 따로 기록한다.
수정(Update)
특정 도큐먼트의 특정 필드를 업데이트 하는 방법은 아래와 같은 식이다.
db.collection.update({key: value, ...}, {$set: {key: value, ...}})
- 첫 매개변수는 어떤 도큐먼트인지 검색하기 위한 조건으로 find 에서 쓰는 쿼리와 동일하다.
- 두 번째 매개변수는 업데이트 하려는 내용을 적는 곳이다.
위 예제는 특정 필드의 값을 업데이트(set) 하려는 경우이고, 도큐먼트를 통째로 갈아 엎으려면 insert 명령과 비슷하게 그냥 두 번째 매개변수에 도큐먼트를 그냥 넣어버리면 된다.
참고로 특정 버전 이후부터 update
명령은 한 개의 도큐먼트만 수정하게 바뀌었다. 모든 도큐먼트 대상으로 업데이트를 하려면 updateMany
명령을 사용하면 된다. 물론 매개변수는 동일하게 사용할 수 있다.
삭제(Delete)
특정 하나의 도큐먼트를 검색해서 삭제하는 방법은 아래와 같다.
db.collection.deleteOne({key: value, ...})
당연히 find 에서 쓰던 쿼리를 그대로 쓸 수 있다.
해당하는 여러 도큐먼트를 한 번에 삭제하고 싶다면 deleteOne
대신 deleteMany
를 사용하자. 사용법은 동일하다.
검색(find) 관련 노트
정렬, 위치, 갯수 제한
db.collection.find({key: value, ...}) .sort({field: -1}) .skip(5) .limit(10)
sort
- 위의 경우 field 라는 프로퍼티를 기준으로 내림차순(Descending)으로 정렬된 결과를 얻을 수 있다. 오름차순으로 정렬하려면 -1 대신 1을 넣으면 된다.
skip
- 검색된 도큐먼트들 중 앞의 몇 개를 생략한다. 위의 경우 첫 5개는 생략한다는 의미다.
limit
- 검색된 도큐먼트 중 몇 개만 가져온다. 위의 경우 skip 된 이후에 10개의 도큐먼트를 얻어온다는 의미다.
수치 비교
db.collection.find({key: {$gt: 10}})
안타깝게도 일반적으로 쓸 수 있는 수치 비교 연산자인 꺽쇠(>
, <
)를 쓰지는 못 하고 대신 의미를 가지는 아래 오퍼레이터를 사용할 수 있다.
$gt
- 왼쪽이 오른쪽보다 큼(Greater Than)
$lt
- 왼쪽이 오른쪽보다 작음(Less Than)
$gte
- 왼쪽이 오른쪽 보다 크거나 같음(Greater Than or Equal)
$lte
- 왼쪽이 오른쪽 보다 작거나 같음 (Less Than or Equal)
특정 필드 표시하지 않기
db.collection.find({key: value, ...},
{keyToHide: 0})
find()의 두 번째 필드는 여러 옵션을 줄 수 있는데 이렇게 특정 필드를 결과에서 생략할 수도 있다.
특정 필드가 있는 도큐먼트 검색하기
db.collection.find({key: {$exists: true}})
$exists
를 이용해 특정 필드가 있는 문서 만을 검색할 수 있다. 물론 $exists
의 값을 false
로 해서 특정 필드가 없는 도큐먼트를 조회하는 것도 가능하다.
Not Null
db.collection.find({key: {$ne: null}})
참고로 ne
는 Not Equal 의 약자다.
리스트에 특정 아이템이 있는지 검색하기
db.collection.find({some_list: {$all: ['item1', 'item2', 'item3']}})
위의 커맨드에서 some_list
키는 여러 문자열 데이터를 담고 있는 리스트(list or array)고 여기에 item1, item2, item3이 모두 들어있는 것만 검색이 된다.
여러 후보들 중 일치하는 것 검색하기
db.collection.find({key: {$in: ['item1', 'item2', 'item3']}})
위 명령은 key
필드의 데이터가 item1, item2, 혹은 item3 중 하나일 경우 검색된다.
어그리게이트(Aggregate)
어그리게이트는 도큐먼트를 파이프 라인을 통해 여러 차례에 걸쳐서 처리할 수 있도록 하는 특수한 기능이다. 마치 UNIX 유틸리티를 파이프로 묶어서 결과물을 처리하고 이걸 결과로 넘기는 식이 일렬로 처리되는 것과 비슷하다.
기초
어그리게이트의 기본 문법은 아래와 같다.
db.collection.aggregate([{SYNTAX}, ...])
aggregate
의 매개변수가 리스트라는 점에 주의하자. 리스트 안에 나열되는 식들은 각각 함수나 유틸리티 형태이고, 이 리스트의 순서대로 데이터가 흐르며 처리된다.
예제
db.user.aggregate([ {$match: {created: {$gte: ISODate("2000-01-01T00:00:00")}} }, {$group: {_id: '$address', count: {$sum: 1} }, }, ])
두 개의 기능을 이용한 어그리게이트 예제로, user라는 컬렉션에서 2000년 이후로 가입한 사람들만 간추려서 주소가 같은 사용자의 갯수를 센다고 가정한 예제다.
여기서 제일 처음의 $match
는 find
와 비슷하게 컬렉션에서 도큐먼트를 걸러(filter) 내서 다음으로 넘긴다.
그 다음의 $group
은 앞서 필터링 된 도큐먼트를 받아서 address
라는 필터를 기준으로 도큐먼트의 합을 계산한다. $sum
함수는 데이터의 합계를 구하는 함수인데 이 예제에서는 갯수를 세기 위함이므로 1이라는 숫자로 합한다.
몇 가지 유용한 파이프라인 오퍼레이터
$match
- 필터 혹은 쿼리(find와 비슷)
$group
- 특정한 필드를 기준으로 모으기(grouping)
$project
- 도큐먼트의 모양을 바꿈
$lookup
- 다른 컬렉션의 필드 가져오기(join과 비슷)
$sort
- 정렬
$limit
- 갯수 제한
$count
- 도큐먼트 개수
$unwind
- array를 풀어헤치기
$facet
- 다중 파이프라인 구현
사실상 $match
와 $group
이 가장 많이 쓰이므로 이 둘을 잘 알아두면 유용하게 쓸 수 있다.
더 알고 싶다면 🌏Aggregation Pipeline Stages 문서를 참고해보자.
백업 및 복원(Dump and Restore)
백업(Dump)
아래 예제는 host.foo.bar 라는 DB 서버에서 dbName 이라는 데이터베이스의 collectionName 이라는 컬렉션 중 key의 값이 value인 도큐먼트만 골라서 /foo/bar/dump/directory 라는 디렉터리에 백업하는 명령이다.
mongodump --host host.foo.bar \ --out /foo/bar/dump/directory \ --db dbName \ -c collectionName \ -q '{key: value}'
그냥 자주 쓸 만한 옵션을 다 붙여서 나열한 것이고 이 중에 필요한 것만 골라서 사용하면 된다. 예를 들어 -q
옵션이 없다면 해당 컬렉션의 모든 도큐먼트를 백업하게 된다.
복원(Restore)
복원할 때는 백업할 때 사용했던 디렉터리를 입력으로 넣어주면 된다.
mongorestore --host host.foo.bar /foo/bar/dump/directory
백업(dump)할 때 데이터베이스 관련 정보도 백업 되므로 복원할 때는 다른 옵션이 필요하지 않다.
기타
컬렉션 몽땅 비우기(지우기)
삭제 커맨드에 별 다른 조건을 주지 않으면 당연히 몽땅 지워져 버린다.
db.collection.remove({})
무서운 커맨드니 조심하자.
최신 버전에서는 remove
대신 deleteMany
커맨드를 써야하는 것 같다. 하나만 삭제하는 커맨드는 deleteOne
이다.
Replica Set 에서 Primary 바꾸기
삽질로 알아낸 정보라 이 방법 외에 다른 방법이 있을 수도 있음을 먼저 알린다.
우선 mongo CLI 도구로 접속해서 설정을 얻어보자.
> cfg = rs.conf()
여기서 members 의 내용에서 ip 주소를 이용해 무엇이 primary인지 파악해보자. 파악이 되면 primary가 아닌 것들의 priority를 낮춰야 한다.
> cfg.members[1].priority = 0.5
1은 그냥 예제일 뿐이고 정확한 인덱스를 입력해야 한다. 0.5라는 수치도 그냥 예제이며 그냥 primary의 priority 보다 작기만 하면 된다.
수치를 다 바꿨으면 설정을 업데이트 해야 한다.
> rs.reconfig(cfg)
이러면 해결이 되면 좋은데 가끔 다시 바뀌는 경우도 있어서 참 곤란한 녀석이다.