개발/학습

MongoDB 강의 내용 정리 - 2.

sihoonchris 2024. 4. 12. 19:55

(MongoDB 강의 내용 정리 - 1. 에 이어서 진행되는 내용)

[ 순서 ]

4. Delete
5. Session & Transaction
6. 검색
7. 맵 리듀스



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

 

 

4. D (삭제)
(1) * 예시로 바로 설명
 > db.col3.deleteOne({a:10})
    a필드 값이 10인 document를 삭제한다.
    (document가 여러 개라면, 그 중 최우선으로 검색된 document를 삭제한다.)
 > db.col3.deleteMany({a:10})
    a필드 값이 10인 document 전체를 모두 삭제한다.

5. 세션 & 트랜잭션
(1)
Session ?
    - 같은 사용자에게서 온 명령인지 아닌지 구분하기 위해 사용됨
 > db.getMongo().startSession()
     Session Id를 생성
 > sessionId = db.getMongo().startSession()
     "sessionId"라는 변수에 Session Id를 저장
 > sessionId.endSession()
    해당 Session Id에 대한 Session을 종료
    * . endSession을 했더라도 "sessionId"라는 변수의 값은 여전히 존재한다 (단순히 Session이 종료되는 것임)

(2)
Transaction ?
    - 목적
       A의 계좌에서 B의 계좌로 100을 이체한다고 해보자.
      그럼 2개의 명령문이 실행되어야 한다.
          1) A계좌에서 -100
          2) B계좌에서 +100
      그런데 무슨 이유에서인지 1)은 실행이 되었는데, 2)는 실행이 되지 않았다면?
      그러면 100은 그냥 사라져버린 것이 된다.

      이런 상황을 막기 위해
      여러 개의 명령들을 하나의 트랜잭션에 묶어서 실행시키는데,
      이 경우에 만약 명령문들 중 하나라도 에러가 난다면
      트랜잭션 내에서 실행되었던 모든 명령은 실행이 취소된다.
      (이러한 속성을 원자성이라고 하는데, 다음에 기회될 때 자세히 알아보자)
    - 세션이랑 무슨 상관?
      여러 사람이 같은 명령문을 실행시켰을 때,
      두 번째 실행시킨 명령문에서 에러가 났다해서 첫 번째로 실행이 완료된 명령문을 다시 취소시키면 안되니까.
      (트랜잭션 => 안전성 , 세션 => 독립성 으로 보면 될 듯) 
    - 사용법
      * 트랜잭션은 복제되었거나, 샤딩이 된 환경에서만 사용 가능
        그 외의 환경에서는 에러가 나도 트랜잭션이 작동 안함
      예시)
      > sessionId = db.getMongo().startSession()
         sessionId.startTransaction({readConcern:{level:'snapshot'}, writeConcern:{w:'majority'}})
         db.col2.updateOne({name:"홍길동2"}, {$inc:{age:-10}})
         db.col2.updateOne({name:"호세"}, {$inc:{age:10}})
         sessionId.commitTransaction()
         sessionId.endSession()
      * startTransaction 안의 옵션들은 나중에 알아보자.
        Replica Set, Arbiter 등등 추가적인 개념들이 더 있으나
        이는 개발자보다는 서버 관리자에게 더 크게 요구되는 지식이다 - 난 개발자임

6. 검색   * 예시로 바로 설명
(1) 관계 연산자
 > db.col2.find( { age: {$gte:21} } )
    age필드의 값이 21이하인 document들을 조회
    * 
    $gt   : greater than 
    $gte : greater than, or equal
    $lt    : less than
    $lte   : less than, or equal
    $ne   : not equal
 > db.col2.find({age:{$gte:21, $lte:50}})
    age필드의 값이 21이상, 50이하 인 document들을 조회
 > db.col2.find( { age: {$nin: [10, 21] } } )
    (배열 활용) age필드의 값이 10 또는 21이 아닌 document들을 조회
    * nin : not-in

(2) 정규표현식
 > db.col2.find( { name: {$regex: '홍'} } )
    name필드 값에 '홍'이 포함되는 document 조회
    * 
    '^홍'  :  '홍'으로 시작되는 문자열
    '홍$'  :  '홍'으로 끝나는 문자열

(3) 배열 값 검색
 > db.col2.find( {'etc': {$elemMatch: {'likenum': {$in: [10, 22]} } } } )
    etc필드의 배열값 likenum에, 요소로 10 또는 22를 가지고 있는 document를 조회 
 > db.col2.find( {'etc': {$elemMatch: {'likenum': {$nin: [10, 22]} } } } )
    etc필드의 배열값 likenum에, 요소로 10 또는 22가 아닌 값을 가지고 있는 document를 조회
    (배열 안에 10 또는 22가 있는 document를 걸러내는 옵션이 아니다.)
 > db.col2.find( {'etc': {$elemMatch: {'likenum': {$all: [14, 22, 3, 4, 5]} } } } )
    etc필드의 배열인 likenum 전체의 값이 [14, 22, 3, 4, 5]와 일치하는 document를 조회
 > db.col2.find( {'etc': {$elemMatch: {'likenum': {$size: 5} } } } )
    etc필드의 배열인 likenum의 길이가 5인 document를 조회

(4) 논리 연산자
 > db.col2.find( {$and: [ {age:{$gt:10}}, {age:{$lt:50}} ] } )
    10 < age < 50 인 document를 검색
 > db.col2.find( {$or: [ {age:{$gt:10}}, {age:{$lt:50}} ] } )
    age > 10 또는 age < 50 인 document

(5) 텍스트 연산자
     - 텍스트 연산자 사용하려면 "인덱스" 필요
     - 인덱스?
           - 보다 빠르고 편리하게 검색 가능 (자주 검색하는 필드에 설정해주면 좋음)
           - 숫자, 문자열만 허용, object는 인덱스로 설정 불가능

 > db.col2.createIndex({name:"text"})
    name필드에 인덱스 지정
 > db.col2.createIndex( {name:"text" , address:"text"} )
    name필드와 address필드를 인덱스로 설정
 > db.col2.dropIndexes()
    설정된 인덱스 삭제

(name필드가 인덱스로 설정되어 있을 때)
 > db.col2.find({$text: {$search: '호세'}})
    (name필드를 지정해주지 않았어도) name필드의 값이 '호세'인 document를 검색
 > db.col2.find( {$text: {$search: 'mike', $caseSensitive:true} } )
    $caseSensitive : 대소문자를 구별하여 검색
 > db.col2.find({$text: {$search: "호세, 홍길동"}})
    name필드의 값이 호세 또는 홍길동 인 document를 검색
 > db.col2.find({$text: {$search: "\"호세, 홍길동\""}})
    name필드의 값이 "호세, 홍길동"인 document 검색

(6) 배열 검색 심화
likenum 배열 안에 22가 있는 document를 검색
 > db.col2.find({etc: {$elemMatch: {likenum: 22}}})
    * 해당되는 document의 field 전체를 출력
 > db.col2.find({}, {etc: {$elemMatch: {likenum: 22}}})
    * 해당되는 document는 field 중에서 배열 field만 출력
      해당되지 않는 document는 id만 출력 
 > db.col2.find({etc: {$elemMatch: {likenum: 22}}}, {"etc.$":true})
    * 해당되는 document는 field 중에서 배열 field만 출력
      해당되지 않는 document는 출력하지 않음
 > db.col2.find({etc: {$elemMatch: {likenum: 22}}}, {"etc.likenum": {$slice: 1}})
    * 해당되는 document의 field값 배열에서 첫 번째 요소만 출력함(인덱스 번호로 바꾸면 0번인 값)
 > db.col2.find({etc: {$elemMatch: {likenum: 22}}}, {"etc.likenum": {$slice: [1,3]}})
    * 해당되는 document의 field값 배열에서 1번째에서 3번째 요소(총 3개)를 출력함(이 때는 인덱스 번호를 기준으로 함)

7. 맵 리듀스
(생략)

이유 1) 버전 차이(나 7 , 강의 4.2) : .mapReduce()는 deprecated된 함수임
이유 2) 솔직히 뭔소리인지 못알아듣겠음

이유 3) 현재 내가 진행하는 프로젝트에서 크게 필요로 하는 개념은 아님

 

 


 

우선 여기까지 공부하고, 다시 프로젝트로 넘어가자