Ynghan 2023. 12. 18. 10:43

몽고디비의 장점

데이터를 다루는데 있어 좋은 데이터베이스

  • 쉬움 - 자연스럽고 직관적
    • JSON 형식 저장에 적합
    • 쿼리가 단순함
  • 유연성 - 데이터 변경이 쉽고, 빠르게 적용됨
    • 몽고디비는 Schema-less이다.
  • 빠름 - 불필요한 작업없이 좋은 성능을 제공함
    • 불필요한 조인과 연산 없음
    • ORM 생략
  • Versatile - 다양한 데이터 및 쿼리를 지원
    • JSON을 잘 저장하는 것과 더불어 빠르게 읽을 수 있어야 함
    • JSON의 까다로운 점 - 파싱, 필터링, 인덱싱, ..

원하는 곳에 다양한 방법으로 데이터를 저장하는 데이터베이스

  • Availability(고가용성) - 정교한 복제 및 장애 극복
    • 분산 환경에 데이터를 저장
    • RDB의 경우 "관계"라는 특징으로 분산 환경 구축이 어려움
    • MongoDB의 경우 리플리카 셋을 이용하여 HA(High Availability)를 제공
  • Scalability - 저장 시스템을 유연하게 확장할 수 있는 능력
    • 최근 데이터의 폭발적인 증가로 데이터베이스의 Scalability가 DB를 선택하는 주요 특징이 됨
    • Scale-out(서버를 병렬적으로 추가)
    • MongoDB는 샤딩을 통해 높은 Scalability를 제공

RDB와의 비교

RDB vs MongoDB

  • 테이블 ↔ 컬렉션
  • 행 ↔ 도큐먼트
  • 컬럼 ↔ 필드

JSON(JavaScript Object Notation)

  • JavaScript에서 객체를 만들 때 사용하는 표현식
  • 특정 언어나 플랫폼에 종속적이지 않음
  • JavaScript Object와의 차이점
    • JS Object : 메모리 안에 있는 데이터 구조
    • JSON : 객체의 내용을 기술하기 위한 텍스트 파일
    • JSON.parsing() : JSON → JS Object
    • JSON.stringify() : JS Object → JSON

기본 개념

JSON vs BSON

  • JSON의 단점
    • 파싱이 매우 느리고, 메모리 사용이 비효율적
    • 기본 데이터 타입만 지원
  • BSON(Binary JavaScript Object Notation)
    • JSON과 동일한 구조, Binary 형태
    • 네트워크를 통한 데이터 전달
    • 문자열 길이를 추가 저장, 데이터 탐색에 용이
  • MongoDB는 속도, 효율성, 유연성의 장점으로 내부적으로 BSON 형식으로 데이터를 저장, 사용한다.

도큐먼트 생성, 갱신, 삭제

Documents

BSON documents

  • JSON보다 더 많은 데이터 타입을 포함
  • 키-값 쌍으로 구성
    • 필드 명을 따옴표로 묶는 것이 좋음

_id와 ObjectId

  • _id
    • MongDB에 지정된 모든 도큐멘트는 "_id" 키를 가짐
    • _id의 값은 ObjectId가 기본
    • 동일 컬렉션(테이블) 내에서만 유일성 보장
  • ObjectId
    • 전역적으로 유일한 값을 생성하기 용이
    • 크기 : 12Byte
      • 4-byte : timestamp
      • 5-byte : random value
      • 3-byte : incrementing counter

MongoDB 시작

MongoDB를 조작하는 방법

  • MongoDB 쉘
  • Compass
  • Mongoose

MongoDB 셸

  • MongoDB 인스턴스와 상호작용하는 자바스크립트 셸 제공
  • 표준 자바스크립트 라이브러리 모든 기능 활용 가능
  • mongo를 입력해 실행 가능
  • compass에서도 실행 가능

두 종류의 데이터베이스

  • default database 또는 reserve database
    • admin : 인증과 권한에 관한 정보 저장
    • config : 샤딩에 관한 정보 저장
    • local : 리플리카 셋 동작을 위해 필요한 정보 저장

기본 명령어

  • 현재 데이터베이스 확인 - db
  • 사용할 데이터베이스 선택 - use users
  • 셸 기본 작업 - CRUD : 생성, 읽기, 갱신, 삭제

Insert Documents

삽입

  • insertOne
  • insertMany

insertOne

  • db.collection.insertOne()
  • 도큐먼트에 pk와 같은 _id가 자동 추가
  • 최대 16 megabytes
use testdb
db.products.insertOne( { item: "card", qty: 15 });

insertMany

db.collection.insertMany(
    [<document 1>, <document 2>, ...],
{
    writeConcern: <document>,
    ordered: <boolean>
}
)
  • bulk insert용 : 데이터베이스로 왕복하지 않고 도큐먼트를 대량 삽입
  • MongoDB는 한 번에 일괄 삽입할 수 있는 데이터 크기 제한이 있어 크기가 넘어갈 경우 여러 개로 분할 저장
  • ordered(Optional, Default → true)
    • true : 도큐먼트가 제공된 순서대로 삽입.
    • false : 성능 개선을 위해 삽입 순서 재배열

추가 사항

  • 유효성 검사
    • 최소한의 유효성 검사 수행
    • "_id" 필드가 없다면 새로 추가
    • 도큐먼트 크기 제한 검사 : 16M

Select(find)

find()

  • db.collection.find(query, projection)

query

  • 쿼리 연산자(query operator)를 이용하여 필터 기능 수행
db.inventory.insertMany(
[
    {item:"journal", qty: 25, size:{h: 14, w: 21, uom: "cm" }, status: "A"},
    {item:"notebook", qty: 50, size:{h: 8.5, w: 11, uom: "in" }, status: "A"},
    {item:"paper", qty: 100, size:{h: 8.5, w: 11, uom: "in" }, status: "D"},
    {item:"planner", qty: 75, size:{h: 22.85, w: 30, uom: "cm" }, status: "D"},
    {item:"postcard", qty: 45, size:{h: 10, w: 15.25, uom: "cm" }, status: "A"}
]
)
  • Select All
    • {}
  •  Equality Condition
    • { <field1>: <value1>, ... } →  { status: "D" }
    • SELECT * FROM inventory WHERE status = "D"
  •  Query Operator
    • { <field1>: { <operation1> : <value1> }, ... } →  { status: { $in: ["A", "D" ] }}

query an Array

  • db.inventory.find( { tags: "red" } ) : tags에 red 요소가 있다면 매칭(in 쿼리와 유사)
  • db.inventory.find( { tags: ["red", "blank"] } )

dot notation

  • 배열의 특정 원소에 접근하거나, embedded Document에 접근할 때 사용
  • 배열
    • <array>.<index>
  • embedded Document
    • <embedded document>.<field>
      • {"size.h":14}
      • {"size.h": {$gt:14}}

query

  • AND conditions
    • 쿼리를 콤마로 나열할 경우, 암묵적으로 and 논리 관계
    • { status: "A", qty: {$lt: 30}}
    • SELECT * FROM inventory WHERE status = "A" AND qty < 30
  • OR conditions
    • { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] }
    • SELECT * FROM inventory WHERE status = "A" OR qty < 30
  • AND + OR
    • { status : "A", $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ] }
    • SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")

projection

  • 조회된 도큐먼트에서 원하는 키(필드) 값만 선별하여 수신
    • db.inventory.find({status: "D"}, ["status"])
    • db.inventory.find({status: "D"}, {"status":"A"}) → error!!
  • 값에 0과 1을 사용하여 포함할 필드(1)와 제외할 필드(0)를 지정할 수 있음
    • db.inventory.find({status:"D"}, { item: 1, status: 1})
    • db.inventory.find({status: "D"}, { item: 1, _id: 0 })

Update

치환과 갱신

  • 치환/갱신 함수는 두 개의 파라미터를 받음 1) 필터 2) 변경 사항
    • replaceOne(치환) : 일치하는 문서 완전 교체
    • updateOne, updateMany(갱신) : 필드 부분 갱신
db.restaurant.insertMany(
[
{ "_id" : 1, "name" : "Central Perk Cafe", "Borough": "Mangattan" },
{ "_id" : 2, "name" : "Rock A Feller Bar and Grill", "Borough": "Queens", "violations": 2 },
{ "_id" : 3, "name" : "Empire State Pub", "Borough": "Brooklyn", "violations: 0 }
]
)

replaceOne

db.restaurant.replaceOne(
{ "name" : "Central Perk Cafe" }, //필터
{ "name" : "Central Pork Cafe", "Borough" : "Manhattan" } //변경 사항
)
  • 치환이 실패할 경우
    • { "acknowledged" : true, "matchedCount" ; 0, "modifiedCount" : 0 }
  • Upsert(update or insert)
    • 수정 대상이 없을 경우 insert
db.restaurant.replaceOne(
{ "name" : "Pizza Rat's Pizzaria" }, // 필터
{ "_id" : 4, "name" : "Pizza Rat's Pizzaria", "Borough" : "Manhattan", "violations" : 8 }, // 변경 사항
{ upsert: true } //upsert 사용
)

updateOne()

  • 부분 갱신에서 갱신 연산자 사용
  • 갱신 연산자는 키(필드)를 변경, 추가, 제거 등의 복잡한 갱신 연산을 지정하는 데 사용하는 특수키
db.restaurant.updateOne(
{"name" : "Central Pork Cafe" },
{$inc: {"violations" : 1}}
)
db.restaurant.updateOne(
{ "name" : "Rock A Feller Bar and Grill" },
{ $set: {"violations" : 3} }
)
db.restaurant.updateOne(
{ "name" : "Rock A Feller Bar and Grill" },
{ $inc: { "violations" : 3 } }
)

updateMany()

  • 컬렉션에 대해 특정 필터에 맞는 모든 documents가 갱신된다. 
db.restaurant.updateMany(
{ violations: { $gt": 4} }, //이 필터에 해당하는 모든 도큐먼트가 변경됨
{ $set: {"Review": true }}
)

Delete

  • 삭제
    • deleteOne : 필터와 일치하는 첫 번째 도큐먼트 삭제(_id 아닌 중복 가능한 필드로 필터를 작성할 경우)
    • deleteMany : 필터와 일치하는 모든 도큐먼트 삭제
db.restaurant.deleteOne({ _id: 1})
db.restaurant.deleteMany({Review:true})
  • drop
    • 전체 도큐먼트 삭제
    • delete 또는 drop 작업을 취소(Undo)하거나 복구하는 방법이 없음
db.restaurant.drop()