DB의 민족/MongoDB

Chapter 2. 몽고DB 기본

댕구리댕댕구리 2022. 11. 23. 02:24
728x90
반응형
SMALL
  • 몽고DB 데이터의 기본 단위는 도큐먼트이며, 이는 관계형 데이터베이스의 행과 유사
  • 같은 맥락에서 컬렉션은 동적 스키마가 없는 테이블과 같음
  • 단일 인스턴스는 자체적인 컬렉션을 갖는 여러 개의 독립적인 데이터베이스 호스팅
  • 모든 도큐먼트는 컬렉션 내에서 고유한 특수키인 '_id'를 보유
  •  몽고 DB는 몽고 셸이라는 간단하지만 강력한 도구와 함께 배포
    • 몽고 셸은 몽고DB 인스턴스를 관리하고 몽고DB 쿼리 언어로 조작하기 위해 내장 지원을 제공
    • 사용자가 다양한 목적으로 자신의 스크립트를 만들고 로드할 수 있는 완전한 기능의 자바스크립트 해석가

 

 

1. 도큐먼트

  • 'greeting'이라는 키와 연결된 'Hello world!'라는 값
{"greeting" : "Hello, world!"}

 

  • 도큐먼트의 값은 단지 blob형이 아닌, 값은 데이터형이여야함
  • "greeting"의 값은 문자열이며 "views"의 값은 정수
{"greeting" : "Hello, world!", "views" : 3}

 

  • 도큐먼트의 키는 문자열이지만, 아래의 예를 제외하면 어떤 UTF-8 문자든 쓸 수 있음
  1. 키는 \0(null 문자)을 포함하지 않는다. \0은 키의 끝을 나타내는데 사용
  2. .과$ 문자는 몇 가지 특별한 속성을 가져 특정 상황에서만 사용. 보통 예약어로 취급(부적절 사용시 경고)

 

  • 몽고DB는 데이터형과 대소문자를 구별
  • 아래 두 도큐먼트는 서로 다름
{"count" : 5}
{"count" : "5"}
  • 아래도 마찬가지
{"count" : 5}
{"Count" : 5}

 

 

2. 컬렉션

  • 컬렉션은 도큐먼트의 모음

2 - 1. 동적 스키마

  • 아래 다음 도큐먼트들을 하나의 컬렉션에 담을 수 있음
{"greeting" : "Hello world!","views" : 3}
{"signoff" : "Good night, and good luck"}

 

  • 다른 구조의 도큐먼트라도 같은 컬렉션에 저장할 수 있지만, 별도의 컬렉션이 필요한 이유
    1. 같은 컬렉션에 다른 종류의 도큐먼트를 저장하면 개발자와 관리자에게 번거로운 일 발생
    2. 컬렉션별로 목록을 뽑으면 한 컬렉션 내 특정 데이터형별로 쿼리해서 목록을 뽑을 때보다 훨씬 빠름
    3. 같은 종류의 데이터를 하나의 컬렉션에 모아두면 데이터 지역성에 좋음
    4. 인덱스를 만들면 도큐먼트는 특정 구조를 가져야함. 이러한 인덱스는 컬렉션별로 정의하는데, 같은 유형의 도큐먼트를 하나의 컬렉션에 넣음으로써 컬렉션을 효율적으로 인덱싱 가능

 

2 - 2. 네이밍

  1. 빈 문자열(" ")은 유효한 컬렉션명이 아님
  2. \0(null)은 컬렉션 명의 끝을 나타내는 문자이므로 컬렉션 명에 사용 불가능
  3. system.으로 시작하는 컬렉션명은 시스템 컬렉션에서 사용하는 예약어이므로 사용 불가능
    1. system.users = 데이터베이스 사용자 정보
    2. system.namespaces = 데이터베이스 내 모든 컬렉션의 정보
  4. 사용자가 만든 컬렉션의 이름에 예약어인 $를 포함 불가
  • 서브컬렉션
    • 네임스페이스에 .(마침표) 문자를 사용해 컬렉션을 체계화
    • 예를 들어 블로그 기능이 있는 어플리케이션은 blog.posts / blog.authors 라는 컬렉션을 가지는데 이는 단지 체계화를 위함 / blog 컬렉션이나 자식 컬렉션과는 아무런  관계가 없음
    • 데이터를 체계화하는 훌륭한 접근 방법

 

3. 데이터베이스

  • 데이터베이스는 컬렉션과 마찬가지로 이름으로 식별
  • 제약조건
    1. 빈 문자열(" ") 유효한 데이터베이스 이름이 아님
    2. 데이터베이스 이름은 다음 문자를 포함 불가(\, /, ., ' ', *, <, >, :, |, ?, $, (단일공간), \0(null문자))
    3. 데이터베이스 이름은 대소문자 구별
    4. 데이터베이스 이름은 최대 64바이트
  • 특별한 의미를 가지는 데이터베이스
    1. admin
      • 인증권한 부여 역할
      • 일부 관리 작업을 하려면 admin에 대한 접근 권한필요
    2. local
      • 단일 서버에 대한 데이터를 저장
      • 복제 셋에서 local은 복제 프로세스에 사용된 데이터 저장
      • local 자체는 복사 불가능
    3. config
      • 각 샤드의 정보를 저장
  • 컬렉션을 저장하는 데이터베이스의 이름을 컬렉션명 앞에 붙이면 올바른 컬렉션명인 네임스페이스를 얻음
  • 예로 cms 데이터베이스의 blog.posts 컬렉션을 사용할 경우 네임스페이스는 cms.blog.posts
  • 네임스페이스의 최대 길이는 120바이트이지만, 실제로는 100바이트 이내가 이상적

 

 

4. 몽고DB 시작

  • 환경에 맞게 다운로드
  • 아래 블로그는 윈도우 버전 기준

링크

 

[MongoDB] 윈도우 몽고디비 설치 방법

1. 설치파일 다운로드 https://www.mongodb.com/try/download/enterprise MongoDB Enterprise Server Download Download MongoDB Enterprise Server, which provides advanced security and performance options for the most demanding apps. Use for free for devel

joytk.tistory.com

  • 사용할 Tool 설치

링크

 

Thanks for downloading Studio 3T | Studio 3T

Thanks for downloading Studio 3T! You’re seconds away from a better way of working with MongoDB. Your download should begin shortly.

studio3t.com

참고 영상

 

5. 몽고DB 셸 소개

  • 인스턴스와 상호작용하는 자바스크립트 셸 제공
  • 셸은 관리 기능이나, 실행 중인 인스턴스를 점검하거나 간단한 기능을 시험하는데 유용

 

5 -1. 셸 실행

$mongo

x = 200;
x /5;

Math.sin(Math.PI / 2)

 

출력값 : 1

 

 

 

  • 자바스크립트의 함수를 정의하고 호출도 가능
function factorial (n) {
	if (n <=1) return 1;
    return n*factrial(n-1);	
}

factorial(5);

출력값 : 120

 

 

5 - 2. 몽고DB 클라이언트

db;

 

출력값 : test(각자의 db 이름이 출력)

 

 

  • 중요한 데이터베이스 선택
use viseo;

db;

 

 

5 - 3. 셸 기본 작업

 

생성

  • 셸의 기본 작업인 생성, 읽기, 갱신, 삭제는 CRUD로 정리
movie = {"title" : "Star Wars : Episode IV - A New Hope",
        "director" : "George Lucas",
        "year" : 1977};

 

  • insertOne 함수는 컬렉션에 도큐먼트를 추가
db.movies.insertOne(movie);

 

  • 영화가 데이터베이스에 저장. 컬렉션에 find를 호출해서 확인
db.movies.find().pretty();

 

  • "_id" 키가 추가됐고 다른 키/값 쌍들은 입력한 대로 저장

 

읽기

  • find / findOne은 컬렉션을 쿼리하는데 사용
  • 컬렉션에서 단일 도큐먼트를 읽으려면 findOne 사용
db.movies.findOne()

 

  • find / findOne은 쿼리 도큐먼트 형태로 조건 전달도 가능 ㅡ> 따라서 쿼리에서 일치하는 도큐먼트 결과를 제한
  • 셸은 find와 일치하는 도큐먼트를 20개까지 자동으로 출력(그 이상도 가능)

 

갱신

  • 게시물 갱신에서는 updateOne을 사용
  • updateOne의 매개변수는 최소 2개 
    1. 수정할 도큐먼트를 찾는 기준
    2. 갱신 작업을 설명하는 도큐먼트
  • 갱신하려면 갱신 연산자 set을 이용
db.movies.updateOne({title : "Star Wars : Episode IV - A New Hope"},
					{$set : {reviews : []}});
                    
WiteResult({"nMatched" : 1, "nUpserted" : 0, "nModified" : 1})

 

 

삭제

  • deleteOne과 deleteMany는 도큐먼트를 데이터베이스에서 영구적으로삭제
  • 두 함수 모두 필터 도큐먼트로 삭제 조건을 지정
db.movies.deleteOne({title : "Star Wars : Episode IV - A NEW Hope"});

 

 

6. 데이터형

 

6 - 1. 기본 데이터형 

  • 몽고DB에서 도큐먼트는 자바스크립트 객체(JSON)와 개념적으로 닮음
  • JSON의 표현력은 null, 불리언, 숫자 ,문자열, 배열, 객체만 지원
  • JSON형은 날짜형이 없어서 날짜 다루는데 어려움이 있음
  • 숫자형은 한 가지만 존재
  • 부동소수점형과 정수형을 표현하는 방법은 없으며, 32 / 64비트 구별 불가
  • 함수나 정규 표현식의 표현 방법 없음
  1. null
    • {"x" : null}
  2. 불리언
    • 참과 거짓 값에 사용
    • {"x" : true}
  3. 숫자
    • 셸은 64비트 부동소수점 수를 기본으로 사용
    • {"x" : 3.14} / {"x" : 3}
    • 4바이트 혹은 8바이트의 부호 정수는 각각 NumberInt / NumberLong 클래스 사용
      • {"x" : NumberInt("3")} / {"x" : NumberLong("3")}
  4. 문자열
    • 어떤 UTF-8 문자열이든 문자열형으로 표현
    • {"x" : "foober"}
  5. 날짜
    • 1970년 1월 1일부터 시간을 1/1000초 단위로 나타내는 64비트 정수로 날짜를 저장
    • {"x" : new Date()}
  6. 정규 표현식
    • 자바스크립트의 정규 표현식 문법을 사용
    • {"x" : /foober/i}
  7. 배열
    • 값의 셋이나 리스트를 배열로 표현
    • {"x" : ["a","b","c"]}
  8. 내장 도큐먼트
    • 부모 도큐먼트의 값으로 내장된 도큐먼트 전체를 포함
    • {"x" : {"foo" : "bar"}}
  9. 객체 ID
    1. 도큐먼트용 12바이트 ID
    2. {"x" : ObjectId()}
  10. 코드
    • {"x" : function() {/*.....*/}}

 

6 - 2. 날짜

  • 새로운 날짜를 생성시에는 Date()가 아닌 new Date() 사용
  • 함수로 생성자를 호출하면 실제 객체 Date()가 아닌 날짜의 문자열을 반환
    • 따라서 항상 Date() 생성자 사용시 주의

 

6 - 3. 배열

  • 정렬 연산(리스트, 스택, 큐)비정렬 연산(셋)에 호환성이 있게 사용
  • 예시 ㅡ> {"things"  :  ["pie", 3.14]}

 

6 - 4. 내장 도큐먼트

  • 도큐먼트는 키에 대한 값이 될 수 있는데 이를 내장 도큐먼트
  • 예를 들어 사람의 정보를 나타내는 도큐먼트에 주소를 저장하려면 정보를 'address' 내장 도큐먼트로 중첩
  • "address"에서 키에 대한 값은 "street","city","state"의 키/값 쌍을 갖는 내장 도큐먼트
{
    "name" : "John Doe",
    "address" : {
        "street" : "123 Park Street",
        "city" : "Anytown",
        "state" : "NY"    
    }
}

 

 

6 - 5. _id 와 ObjectId

  • _id는 하나의 컬렉션에서 모든 도큐먼트는 고유하게 가지는 값
  • ObjectIds
    • "_id"의 기본 데이터형
    • 경량으로 설계됐으면서도 여러 장비에 걸쳐 전역적으로 유일한 방법으로 생성 가능
    • 기본키가 아닌 ObjectId를 사용하는 이유는 기본키는 전통적이지만 여러 서버에서 자동으로 증가해 동기화 작업이 어렵고 시간이 오래 걸림
    • ObjectId는 12 바이트 스토리지를 사용하면 24자리 16진수 문자열 표현 가능 / 바이트당 2자리 사용
    • ObjectId 12바이트
      • 더보기
        0(타임스탬프)          1(랜덤)             2(카운터 ㅡ 랜덤 시작 값)                           3 4 5 6 7 8 9 10 11
    • ObjectId의 첫 4바이트는 1970년 1월 1일부터의 시간을 1/1000초 단위로 저장하는 타임스탬프
      • 타임스탬프의 속성
        1. 다음 5바이트와 묶일 때 초 단위의 유일성 제공
        2. 타임스탬프가 맨 처음에 온 다는 것은 ObjectId가 대략 입력 순서대로 정렬된다는 의미
        3. 4바이트에는 각 도큐먼트가 생성된 때마의 잠재적인 타임스탬프 존재
    • ObjectId의 다름 5바이트는 랜덤 값
    • 최종 3바이트는 서로 다른 시스템에서 충돌하는 ObjectId들을 생성하지 않도록 랜덤 값으로 시작하는 카운터
    • 앞 9바이트는 1초 동안 여러 장비와 프로세스에 컬쳐 유일성을 보장
    • 마지막 3 바이트는 단순히 증분하는 숫자로, 1초 내 단일 프로세스의 유일성 보장
    • 고유한 ObjectId는 프로세스당 1초에 256**3(1677만 7216)개까지 생성

 

 

7. 몽고DB 셸 사용

 

7 - 1. 셸 활용 팁

help

  • DB 수준의 도움말 = db.help() / 컬렉션 수준의 도움말 = db.foo.help()

 

 

7 - 2. 셸에서 스크립트 실행하기

  • 단순히 명령행에 스크립트를 넘기면 됨
$mongo script1.js script2.js script3.js

 

 

  • 기본값으로 지정되지 않은 호스트나 포트 mongod에 연결해 사용하는 스크립트 실행
  • --quiet는 "MongoDB shell version v4.2.0" 배너를 미출력
$ mongo server-1:30000/foo --quiet script1.js script2.js script3.js
load("script1.js")

 

 

  • 셸 보조자와 대응하는 자바스크립트 대응법
    • use video = db.getSisterDB("video")
    • show dbs = db.getMongo().getDBs()
    • show collections = db.getCollectionNames()
  • connectTo 함수 정의 방법
// defineConnectTo.js

/**
* 데이터 베이스에 연결하고 db를 설정
*/

var connectTo = function(port, dbname) {
    if (!port){
        port = 27017;
    }
    if (!dname){
    dbname = "test";
    }
    
    db = connect("localhost:"+port+"/"+dbname);
    return db;
    
    }
typeof connectTo
load('defineConnectTo.js)
typeof connectTo
run("ls", "-l", "/home/myUser/my-scripts/")

 

 

7 - 3. mongorc.js 만들기

  • 자주 로드되는 스크립트(셸이 시작할 때마다 실행되는) .mongorc.js 파일에 넣을 수 있음
// .mongorc.js

var compliment = ["attractive","intelligent","like Batman"];
var index = Math.floor(Math.random()*3);

print("Hello, you are looking particularly "+compliment[index]+" today!");

  • .mongorc.js의 일반적인 용법 중 하나는 '더 위험한' 셸 보조자를 제거
  • dropDatabase / deleteIndexes 같은 함수 사용
var no = function(){
    print("Not on my watch")';
    };
    
// 데이터베이스 삭제 방지
db.drppDatabase = DB.prototype.dropDatabase = no;

// 컬렉션 삭제 방지
DBCollection.prototype.drop= no;

// 인덱스 삭제 방지
DBCollection.prototype.dropIndexe = no;

// 인덱스 삭제 방지
DBCollection.prototype.dropIndexes = no;
  • 코드를 실행하게 되면 오류 메세지가 발생
  • 악의적인 사용자로부터 보호하는 기능이 아닌, 의도치않게 키를 잘못 눌러 명령을 실행했을 때 도움
  • 셸을 시작할 때 --norc 옵션을 사용해 .mongorc.js의 로딩을 비활성화

 

7 - 4. 프롬포트 커스터마이징하기

  • 몇 분이 걸리는 쿼리를 실행할때, 마지막 작업이 완료된 시각을 출력하는 프롬프트 생성
prompt = function() {
    return (new Date())+ " > ";
};

 

  • 현재 사용하는 데이터베이스를 보여주는 프롬프트 생성
prompt = function() {
    if (typeof db == 'undefined'){
    return '(nodb)> ';
    }    

// 마지막 db 연산 확인
    try {
        db.runCommand({getLastError:1});
    }
    catch(e) {
        print(e)
    }
    return db+ "> ";

};

 

 

7 - 5. 복잡한 변수 정하기

EDITOR = "/usr/bin/emacs"
  • edit 변수명 형식으로 변수를 편집
var wap = db.books.findOne({title : "War and Peace"});
edit wap

 

 

7 - 6. 불편한 컬렉션명

> db.version


[Function: version] AsyncFunction {
  apiVersions: [ 0, 0 ],
  returnsPromise: true,
  serverVersions: [ '0.0.0', '999.999.999' ],
  topologies: [ 'ReplSet', 'Sharded', 'LoadBalanced', 'Standalone' ],
  returnType: { type: 'unknown', attributes: {} },
  deprecated: false,
  platforms: [ 'Compass', 'Browser', 'CLI' ],
  isDirectShellCommand: false,
  acceptsRawInput: false,
  shellCommandCompleter: undefined,
  help: [Function (anonymous)] Help
}

 

 

  • 컬렉션명이 예약어가 아니거나 유효하지 않은 자바스크립트 속성명이 아니라면 db.collectionName 구문 사용
  • foo-bar-baz 나 abc123과 같은 자바스크립트에 유효하지 않은 문자로 컬렉션명을 만들었을 때도 가능
    • 자바스크립트는 오직 문자, 숫자, $, _만 가능하며, 숫자로 시작 불가능
> db.getCollection("version")

test.version

 

 

  • 다른 방법으로는 배열 접근 구문을 사용해 유효하지 않는 속성명을 피할 수 있음
  • 자바스크립트에서 x.y = x['y']  가능 ㅡ> 서브컬렉션이 상수 이름뿐만 아니라 변수를 이용해서도 접근이 가능함을 의미
var collection = ["posts","comments","authors"]

for (var i in collection){
... print(db.blog[collection[i]]);
	}

  • for 루프 대신에 blog만 사용해서도 가능
print(db.blog.posts);print(db.blog.comments);print(db.blog.authors);

 

  • test.blog.posts가 아닌 test.blog.i로 해석될 수 있는 db.blog.i는 사용 불가
  • i가 변수로 해석되려면 db.blog[i]구문 사
var name ="@&#!"
db[name].find()

참고자료

 

몽고DB 완벽 가이드 - YES24

NoSQL의 진수 몽고DB 개발부터 관리까지몽고DB 입문자를 위한 기초부터 실제 배포에 적용할 수 있는 실용적이고 깊이 있는 내용까지 담았다. 개정 3판에서는 성능이 강화된 몽고DB 최신 버전을 반

www.yes24.com

 

728x90
반응형
LIST