학교수업/빅데이터
MongoDB
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}}
- <embedded document>.<field>
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()