개발/학습

MongoDB 강의 내용 정리 - 1.

sihoonchris 2024. 4. 10. 18:13

[ 순서 ]

0. 시작 전에
1. Create
2. Read
3. Update
4. Delete


* 내가 공부한 내용들은 정리한 글임
  틀린 내용, 부족한 내용이 있을 수 있으니
  (혹시라도 이 글을 볼 사람이 있을 지는 모르겠다만)
  암튼 참고하고 유의하셈

 

0. MongoDB 구조
    - db > collection > document > field
      (RDBMS로 생각하면, db > schema > table > column 정도로 보면 될 듯)
    - show dbs
      전체 DB 검색
    - show collections
      해당 db안의 모든 collection 조회

1. C (생성, 삽입)
(1)
 > use DB이름
    DB를 사용하겠다 (DB가 없으면 만들어서 쓰겠다)
    예) use studydb
 > db . Collection이름 . insertOne ( { document 내용 } ) 
    collection 안에 작성된 document를 삽입하겠다 (collection이 없다면 만든 후 넣겠다)
    예) db.firstcol.insertOne({
              name : "홍길동", 
              age : 10,
              t_f : true,
              assstr : [{국적:"한국", 도시:"서울"},{직업:"육상선수", 경력:"500년"}]
          })
    추가 설명)
        1) 필드 안의 값은 key와 value로 구성됨
             value는 string, number, boolean, object, array 등을 가질 수 있다.
         2) 한 collection 안에서, 각 document들의 field 갯수는 달라도 된다


 * 실행 후 아래와 같은 결과가 나온다? => 성공
   {
        acknowledged: true,
        insertedId: ObjectId('6613cc47a043e026aa5dbea1')
    }
 * ObjectID는 Unix 시간, 기기 ID, 프로세스 ID, 랜덤값으로 구성됨
   그렇기 때문에 document들이 같은 값을 같더라도 ObjectID가 다르다면 다른 값처럼 사용 가능하다

(2)
 > db . collection이름 . insertMany ( [ doc1, doc2, doc3, ... ] )
    한 번에 여러 개의 document를 삽입한다.
    예) db.col2.insertMany([
              { name: '홍길동2' ,  age: 50   ,  etc: [ {hobby:'육상s',    state:'충청south'}, {likenum: [12, 22, 32, 42, 52]        } ] },
              { name: '질럿'     ,  age: 5000 , etc: [ {hobby:'찌르기',   state:'함경도'    }, {likenum: [100, 200, 300, 400, 500]} ] },
              { name: '호세'     ,  age: 38    ,  etc: [ {hobby:'스테이크', state:'뉴욕'      }, {likenum: [14, 22, 3, 4, 5]              } ] }
          ])
 * 아래와 같이 반복문을 사용할 수도 있다.
    for(i=0 ; i<500 ; i++) {
        db.col1.insertOne({a:i})
    }

(3)
 > db . createCollection ( collection이름 , { capped: true 또는 false , size: 숫자 })
    collection을 생성한다.
    예) db.createCollection("col1", {capped:true, size:500})
    * capped는 사이즈 지정 옵션 - 지정한 사이즈를 초과할 시 가장 오래된 데이터를 삭제함
    * 최소 사이즈는 4,096바이트 - 그보다 작은 값을 설정할 시 자동으로 4096바이트를 적용함

2. R (조회, 검색)
(1)
 > db . collection이름 . find()
    collection 안의 모든 document를 조회
    예) db.col2.find()
 > db . collection이름 . find ( { 필드 내용(=조건) } )
    collection 안에서 조건에 해당하는 field를 가진 document들을 조회
    예 1) db.col2.find({name:"홍길동"})
    예 2) db.col2.find({name:'질럿', age:5000})
 > db . collection이름 . findOne  ( { 필드 내용(=조건) } )
    collection 안에서 조건에 해당하는 field를 가진 document들 중 제일 먼저 조회된 것을 출력

(2)
 > db . collection이름 . find ( { $elemMatch: { 배열 내용(=조건) } } )
    배열의 값을 통해 document를 조회할 때는 $elemMatch 를 사용해야 한다.
    예 1) db.col2.find( {etc: {$elemMatch: {"likenum.1" : 22} } } )
            "likenum" 배열의 인덱스값 기준 1번이 22인 document들을 조회
    예 2) db.col2.find( {etc: {$elemMatch: {"hobby": '스테이크'} } } )
             hobby값이 "스테이크"인 document 조회
 * 참고 =>
    {  name: '호세' ,
       age: 38, 
       etc: [
         { hobby: '스테이크' , state: '뉴욕' } , 
         { likenum: [14, 22, 3, 4, 5] }
       ]
   }

(3)
Cursor ?
   - Document가 지나치게 많으면 조회시 성능 문제를 야기함 => 이를 해결하기 위한 것이 Cursor
   - Cursor에는 Pointer가 있고, 그 Pointer에는 위치 정보가 들어 있음
   - Cursor를 쓰는 다른 이유 => 다른 언어에서의 접근성
   예) > var cursor = db.col3.find()
         > cursor 
            * 실행결과 : 저장된 Document들
> cursor.next()
   cursor 명령어 실행시 처음으로 출력된 결과값 이후의 값을 하나씩 출력
cursor.hasNext()
   다음 document가 있으면 true, 없으면 false
cursor.toArray()
   cursor 내용 전체 출력 (배열 형식)
. noCursorTimeout()
   시간 제한이 없는 Cursor를 생성 (기본 생성시, cursor의 수명은 10분)
   예) var cursor = db.col3.find().noCursorTimeout()

(4)
 > db . stats() 
    DB의 상태를 조회
 > db . getCollectionInfos()
    DB 안에 있는 모든 Collection들의 정보를 조회
 > db . serverStatus()
    서버 정보 조회
 > db . collection이름 . stats()
    collection의 상태를 파악
 > db . collection이름 . 속성()
    원하는 속성만 조회한다.
    예) db.col1.totalSize()
         col1의 totalSize 정보를 조회

3. U (수정, 교체)
(1)
 > db . 기존collection이름 . renameCollection ( 새로운collection이름 )
    예) db.firstcol.renameCollection('col1st')
         * 실행 결과 => collection 이름이 firstcol에서 col1st 로 바뀜

(2)
 > db . collection이름 . replaceOne ( { 조건 } , { 교체 내용 } )
    조건에 해당하는 field의 내용을 "교체 내용"으로 바꿔버림 (ObjectId는 동일함)
    예) db.col2.replaceOne({name: "홍길동"}, 
              {name: "뽀로로", age: 5}
          )
          name필드의 값이 "홍길동"인 document의 필드 내용 전체를 {name: "뽀로로", age: 5}로 바꿔버림
 > db . collection이름 . updateOne ( { 조건 } , { $set : 교체 내용 } )
    조건에 해당하는 field에서 "교체 내용"에 언급된 내용만 바꿈
    예) db.col2.updateOne({name: "준석"},
             {$set: {age: 21}}
          )
         name필드의 값이 "준석"인 document에서 age필드의 값을 21로 바꿈

(3)  * 예시를 통해 바로 설명
 > db.col2.updateOne({name: "돌김"},
         {$set: {age: 21, 키:182}}, {upsert:true}
    )
    - $set : 해당 필드만 수정
    - upsert : name필드의 값이 "돌김"인 document가 없을 시 만들겠다
      * upsert = update + insert
 > db.col2.updateOne({name: "준석"},
        {$inc: {age: 10}}
    )
    - $inc : age필드의 값에 10 만큼을 더한다.
 > db.col2.updateOne({name: "준석"},
        {$mul: {age: 2}}
    )
    - $mul : age필드의 값에 2를 곱한다.
 > db.col2.updateOne({name: "준석"},
        {$rename: {age: "year"}}
    )
    - $rename : age필드의 키값을 year로 바꾼다
 > db.col2.updateOne({name: "준석"},
        {$max: {year: 21}}
    )
    - $max : 주어진 값(21)이 year필드의 현재값 보다 크면 주어진 값으로 변경
 > db.col2.updateOne({name: "준석"},
        {$min: {year: 21}}
    )
    - $min : 주어진 값(21)이 year필드의 현재값 보다 작으면 주어진 값으로 변경

(4)
 > db . collection이름 . updateMany ( {조건} , {$set: 수정 내용} )
    조건에 맞는 document 전체에 수정 내용을 적용
    예) db.col2.updateMany({name:'핑크퐁'},
              {$set: {age:10}}
         )
    * updateOne의 경우, 조건에 맞는 document들 중 제일 먼저 검색된 결과에 적용함

(5)
만약 조건이 정의되지 않은 상태에서 updataeOne 또는 updateMany를 할 시
수정 대상을 collection 안의 document 전체로 잡는다. 
 예 1) db.col2.updateOne({},
              {$set: {age:10}}
          )
 예 2) db.col2.updateMany({},
              {$set: {age:10}}
           )

(6)
 field에 Object를 추가  * 예시로 바로 설명 
 > db.col2.updateOne({name:'홍길동2'},
         {$push:{"etc":{"likefood":"아이스크림"}}}
    )
   또는
   db.col2.updateOne({name:'홍길동2'},
        {$addToSet:{"etc":{"likefood2":"슈팅스타"}}}
    )
    * $push와 $addToSet의 차이
       $push는 해당 field(key)에 같은 value가 있어도 추가함
       $addToSet은 해당 field(key)에 같은 value가 있을 시 추가하지 않음 

(7)
field에 Array를 추가  * 예시로 바로 설명
 > db.col2.updateOne({name:'준석'},
        {$push:{'friend':['봉석','현준']}}
    )
    "friend"라는 key를 가진 새로운 field에 ['봉석', '현준']이라는 Array를 value로 추가
 > db.col2.updateOne({name:'홍길동2'},
        {$push:{'etc':{'coworker':['김씨','이씨','박씨']}}}
     )
    etc필드에 이름이 coworker인 배열 ['김씨','이씨','박씨']를 추가함

 field에서 Array를 제거  * 예시로 바로 설명 
 > db.col2.updateOne({name:'홍길동2'},
        {$pull:{'etc':{'friend':'김군'}}}
     )
     etc필드에서 '김군'이 들어가 있는 배열 'friend'를 삭제
     (배열의 내용이 수정되는 것이 아니라 배열 자체가 사라짐)

(8)
 Array 내용 수정  * 예시로 바로 설명 
 > db.col2.find({name:'질럿'},
        {$set:{"etc":{'hobby': '베기'}}}
    )
   이 경우, etc필드 안의 모든 객체/배열들이 사라지고
   새로운 value인 {'hobby': '베기'}로 바뀐다
 > db.col2.updateOne({name:'호세'},
         { $set: {"etc.$[el].hobby" : "파스타"} },
         { arrayFilters: [ {"el.hobby" : "스테이크"} ] }
    )
    etc필드 안에 hobby값을 스테이크에서 파스타로 바꿔줌
    * el은 indicator임 - 같게만 쓴다면 어떤 문자를 써도 상관 없음
 * 참고 =>
    {  name: '호세' ,
       age: 38, 
       etc: [
          { hobby: '스테이크' , state: '뉴욕' } , 
          { likenum: [14, 22, 3, 4, 5] }
       ]
    }
 > db.col2.updateOne({name:'홍길동2'},
        {$pop: {'etc':1}}
    )
   etc필드에서 해당 배열 안의 제일 마지막 요소를 삭제
 > db.col2.updateOne({name:'홍길동2'},
       {$pop: {'etc':-1}}
    )
    etc필드에서 해당 배열 안의 제일 첫 요소를 삭제
 > db.col2.updateOne({name:'홍길동2'},
         { $push: { " etc.0.likenum " : 100 } }
    )
    etc필드(배열 형태)의 0번째(인덱스 번호 기준) 값에서,
    해당 값 안에 포함된 "likenum"이라는 배열에 100을 추가
 > db.col2.updateOne({name:'홍길동2'},
        { $push: { " etc.0.likenum " : [101, 102, 103] } }
    )
    etc필드(배열 형태)의 0번째(인덱스 번호 기준) 값에서,
    해당 값 안에 포함된 "likenum"이라는 배열에 [101, 102, 103]을 추가
    (배열 전체가 하나의 요소로서 들어감)
 > db.col2.updateOne({name:'홍길동2'},
         { $push: { " etc.0.likenum " : { $each : [101, 102, 103] } } }
     )
    etc필드(배열 형태)의 0번째(인덱스 번호 기준) 값에서,
    해당 값 안에 포함된 "likenum"이라는 배열에 [101, 102, 103]의 값들을 추가
    (총 3개의 값이 요소로서 들어감)

4. D (삭제)
(1)
 > db . collection이름 . drop()
    collection을 삭제한다.
(2)
 > db . dropDatabase()
    (현재 위치한) db를 삭제한다.