데이터의 구조가 고정되어 있지 않은 데이터베이스를 NoSQL
=> 테이블을 사용하지 않고 데이터를 다른 형태로 저장
NoSQL에서는 데이터를 읽어올 때 스키마에 따라 데이터를 읽어 옴(schema on read)
데이터를 입력하는 방식에 따라, 데이터를 읽어올 때 영향을 미침
ex) 대표적인 NoSQL은 몽고DB
, Casandra
등
Redis
, Dynamo
등MongoDB
Cassandra
, HBase
Neo4J
, InfiniteGraph
NoSQL은 key-value
, document
, wide-column
, graph
등의 방식으로 데이터를 저장
NoSQL은 관계형 데이터베이스보다 동적으로 스키마의 형태를 관리
=> 행을 추가할 때 즉시 새로운 열을 추가할 수 있고, 개별 속성에 대해서 모든 열에 대한 데이터를 반드시 입력하지 않아도 됨
비관계형 데이터베이스의 쿼리는 데이터 그룹 자체를 조회하는 것에 초점
=> 구조화 되지 않은 쿼리 언어로도 데이터 요청이 가능 UnQL(UnStructured Query Language)
NoSQL로 구성된 데이터베이스는 수평적으로 확장
=> 보다 값싼 서버 증설, 또는 클라우드 서비스 이용하는 확장
NoSQL 데이터베이스를 위한 서버를 추가적으로 구축하면, 많은 트래픽을 보다 편리하게 처리 가능
자유로운 형태로 데이터를 저장할 수 있으므로 필요에 따라서 새로운 데이터 유형을 추가 가능
정형화되지 않은 많은 양의 데이터가 필요한 경우, NoSQL이 효율적
데이터베이스를 클라우드 기반으로 쉽게 분리 할 수 있도록 지원하여, 저장 공간을 효율적으로 사용
수평적 확장의 형태로 증설하므로, 이론상 무한대로 서버를 계속 분산시켜 DB를 증설 가능
스키마를 미리 준비할 필요가 없어서, 개발을 빠르게 해야하는 경우에 매우 적합
MongoDB
는 대표적인 NoSQL 도큐먼트 데이터베이스
도큐먼트 데이터베이스는 데이터를 테이블이 아닌, 문서처럼 저장하는 데이터베이스
일반적으로 도큐먼트 데이터베이스에서는 JSON 유사 형식으로 데이터를 문서화
각각의 도큐먼트는 데이터를 필드-값 의 형태로 가지고 있고, 컬렉션이라고 하는 그룹으로 묶어서 관리
NoSQL 데이터베이스에서는 데이터를 행과 열이 아닌, 체계적인 방식으로 저장
ex) 도서카드 목록함
도큐먼트는 객체와 같이 데이터를 필드-값 쌍(Field - Value pair)으로 저장하고 구성
도큐먼트에서 필드는 데이터의 고유한 식별자이고, 값은 주어진 식별자와 관련된 데이터
도큐먼트의 모음을 컬렉션
데이터베이스는 여러개의 컬렉션으로 구성됨
MongoDB에서는 아틀라스(Atlas)로 클라우드에 데이터베이스를 설정
아틀라스는 GUI와 CLI로 데이터를 시각화, 분석, 내보내기, 그리고 빌드하는 데에 사용
아틀라스 사용자는 클러스터를 배포 할 수 있으며, 클러스터는 그룹화된 서버에 데이터를 저장
레플리카 세트
는 동일한 데이터를 저장하는 몇 개의 연결된 MongoDB 인스턴스의 모음
도큐먼트나 컬렉션을 변경할 경우, 변경된 데이터의 중복 사본이 레플리카 세트에 저장됨
레플리카 세트의 인스턴스 중 하나에 문제가 발생하더라도 데이터는 그대로 유지되며, 레플리카 세트의 애플리케이션에서 나머지 작업가능
=> 동일한 데이터를 저장하는 소수의 연결된 머신, 레플리카 세트 중 하나에 문제가 발생하더라도, 데이터를 그대로 유지가능
클러스터(서버 그룹)를 배포하면, 자동으로 레플리카 세트가 구성됨
로컬 또는 클라우드에서 특정 소프트웨어를 실행하는 단일 머신, MongoDB에서는 클라우드에서 실행되는 데이터베이스
데이터를 저장하는 서버 그룹으로 여러 대의 컴퓨터를 네트워크를 통해 연결하여 하나의 단일 컴퓨터처럼 동작하도록 제작한 컴퓨터
shell을 이용하여 도큐먼트를 조회하거나 업데이트 할 때, 도큐먼트는 JSON(JavaScript Object Notation) 형식으로 출력
JSON
은 텍스트 형식이기 때문에 읽기 쉽지만, 파싱이 느리고 메모리 사용이 비효율적
JSON
은 기본 데이터 타입만을 지원하기 때문에, 사용 할 수 있는 데이터 타입에 제약
=> 이런 문제점을 해결하기 위한 방안으로 BSON(Binary JSON) 형식을 도입
BSON
은 컴퓨터의 언어에 가까운 이진법에 기반을 둔 표현법
JSON
보다 메모리 사용이 효율적이며 빠르고, 가볍고, 유연하고 더 많은 데이터 타입을 사용 가능
MongoDB는 JSON형식으로 작성된 것은 무엇이든 데이터베이스에 추가할 수 있고, 쉽게 조회 가능
내부에서는 속도, 효율성, 유연성의 장점이 있는 BSON으로 데이터를 저장, 사용
MongoDB의 데이터는 BSON의 형태로 저장이 되고, 보통 읽기 쉬운 JSON의 형태로 출력됨
mongoimport
와 mongoexport
mongorestore
와 mongodump
모든 MongoDB 도큐먼트는 모든 도큐먼트가 _id 필드를 기본값으로 반드시 가지고 있어야 한다
도큐먼트 내 필드와 값이 똑같다 할지라도, _id 값이 다르면 서로 다른 도큐먼트로 간주
새로운 도큐먼트를 추가할 때, _id 값에 임의적으로 고유한 값을 생성해서 사용할 수도 있지만 보통은 ObjectId 타입(12byte, 24char)의 값으로 사용
또한 도큐먼트를 추가할 때, _id 필드와 값을 특정하지 않았다면, 자동적으로 _id 필드가 생성되고 값에 ObjectId 타입이 할당됨
db.컬렉션이름.insert()
insert() 명령어를 사용하면 주어진 도큐먼트 배열의 인덱스 순서대로 작업이 실행된다.
ordered를 추가하면 순서에 상관없이 고유한 _id를 가진 도큐먼트는 모두 컬렉션에 삽입된다.
사용자가 존재하지 않는 컬렉션에 도큐먼트를 넣는 경우, 그와 동시에 컬렉션이 만들어지게 된다.
db.컬렉션이름.find()
db.컬렉션이름.find().pretty()
: 읽기 편하게 조회됨db.컬렉션이름.find().count()
: 데이터 수db.컬렉션이름.findOne()
: 하나의 데이터 조회db.컬렉션이름.updateOne()
: 주어진 기준에 맞는 다수의 도큐먼트가 있다면, 그 중 작업에 맞는 첫번째 도큐먼트 하나만 업데이트db.컬렉션이름.updateMany()
: 쿼리문과 일치하는 모든 도큐먼트를 업데이트$inc
: 특정 필드 값을 주어진 만큼 증가$set
: 특정 필드 값을 주어진 값으로 바꿔줌$push
: 배열로 이루어진 필드의 값에 요소를 추가하기 위한 연산자db.컬렉션이름.deleteOne()
: 주어진 기준에 맞는 다수의 도큐먼트 중, 첫번째 도큐먼트 하나를 삭제db.컬렉션이름.deleteMany()
: 쿼리문과 일치하는 모든 도큐먼트를 삭제db.컬렉션이름.drop()
: 컬렉션 삭제$eq
(Equal to)$ne
(Not Equal to)$gt
(Greater Than)$gte
(Greater Than or Equal to)$lt
(Less Than)$lte
(Less Than or Equal to)문법: { field : { operator : value } }
쿼리 연산자는 데이터베이스 내에서 데이터를 찾는 다양한 방법을 제공
비교 연산자를 사용하면 특정 범위 내에서 데이터를 찾을 수 있다.
비교 연산자를 지정하지 않으면 $eq가 기본 연산자로 사용
$and
: 지정된 모든 쿼리 절을 충족하는 도큐먼트를 반환$or
: 쿼리 절 중 하나라도 일치하는 도큐먼트가 있다면 해당 도큐먼트를 반환$not
: $nor
의 단일 버전같이 뒤의 조건을 만족하지 않는 모든 도큐먼트를 반환{$not: {statemnet}}
논리 연산자를 사용하면 데이터 검색을 보다 세분화 가능
$expr
: 표현력이 풍부하여 하나 이상의 작업을 수행 가능{ $expr : { expression } }
구문을 사용$expr
를 이용해 변수와 조건문을 사용 가능$expr
를 이용해 같은 도큐먼트 내의 필드들을 서로 비교 가능$를 사용하여 각각의 도큐먼트마다 달라지는 특정 필드의 값을 변수처럼 비교 가능(필드의 값을 참조할 때)
집계 표현식에서 비교 연산자 => {<operator>: {<field>, <value>}}
$push
: 배열에 요소를 추가하거나 이전에 다른 유형의 값이었던 경우 해당 필드를 배열 타입의 필드로 바꿀 수 있다.$all
: 배열 필드에 지정한 요소가 있는 모든 도큐먼트를 반환 /배열 요소의 순서와 상관없이 지정된 요소가 포함된 모든 도큐먼트를 찾을 수 있다.$size
: 특정한 요소를 찾지않는다면, $size만을 사용하여 배열 길이로만 쿼리 가능배열 연산자를 쓰지않고 배열 필드를 쿼리하는 경우 배열을 지정한다면 해당 배열과 정확히 일치하는 배열을 가진 도큐먼트를 찾는다.
문자열로 요소를 지정한다면 해당 요소가 배열에 포함된 모든 도큐먼트를 찾는다.
$elemMatch(projection)
: 지정한 배열 필드가 도큐먼트에 존재하고 조건에 맞는 요소가 있는 경우에만 해당 필드를 결과에 포함시킴$elemMatch(query)
값으로 도큐먼트가 있는 필드가 있고 해당 필드의 값으로 또 도큐먼트가 있는 경우에도 점 표기법을 사용하여 해당 계층에서 도큐먼트 자체가 아닌 필드의 값을 가져올 수 있다.
특정 요소 위치로 배열 필드를 쿼리하거나 서브 도큐먼트의 요소를 쿼리하기 위해 MQL은 점 표기법을 사용하여 도큐먼트에서 이러한 요소의 주소를 지정한다.
점 표기법을 사용하여 원하는 만큼 중첩된 도큐먼트로 이동가능
배열에 점 표기법을 사용하려면 배열에서 요소의 위치를 지정해야한다.
$regex
: 정규식 연산자인$regex
를 사용하여 일치시키려는 문자열을 지정 가능
Aggregation Framework는 MongoDB에서 데이터를 쿼리하는 가장 간단한 방법 중 하나
MongoDB 쿼리 언어를 사용하는 모든 작업은 Aggregation Framework를 사용하여 수행 가능
Aggregation Framework에서는 find가 아닌 aggregate 명령을 사용
aggregate를 사용하면 도큐먼트를 필터링 하지않고 그룹으로 데이터를 집계하거나 데이터를 수정 가능
aggregate를 사용하면 데이터 찾기 및 프로젝션 없이 작업을 수행하거나 계산 가능
aggregate를 사용할땐 대괄호를 이용해 배열을 인자로 사용, 이는 파이프라인처럼 배열 요소의 순서대로 작업을 하기 때문
Aggregation Framework에 $match
등과 같은 필터링 단계가 없으면 데이터 요약, 계산 및 그룹화를 수행 할 때 원본 데이터를 수정하지 않는다는 점을 유의
Aggregation Framework는 데이터를 계산, 재구성 및 재정립하는 기능을 통해 MQL의 필터링 기능을 능가하는 강력한 도구
$match
: 필터링$project
: Projection$group
: 들어온 데이터 스트림을 여러개로 그룹화하는 연산자$group
단계는 이전 단계에서 도큐먼트를 받을 때 _id 필드에 표현식을 사용하여 이 도큐먼트가 속한 그룹을 식별$group
구문의 두 번째 부분을 사용하면 파이프 라인을 통해 들어오는 데이터에 대해 더 많은 양적 분석을 수행 가능$group
과 $sum
을 이용하여 그룹화된 데이터를 리듀스하는 방법
MongoDB_index - memorization
다중 인덱스(compound index)를 만들면, 모든 도큐먼트를 조회할 필요가 없다. 어떤 필드에 대한 인덱스를 만드는 것은 해당 필드의 값을 기준으로 도큐먼트의 위치 정보를 담은 데이터를 생성하는 것이다.
인덱스를 생성하기 위해서는 createIndex()
라는 메소드를 사용
db.collection_name.createIndex({<필드명>:1, <필드명>: -1})
createIndex의 파라미터로 인덱스를 적용할 필드를 전달
이에 따른 값을 1로 지정하면 오름차순으로, -1로 하면 내림차순으로 정렬
이때 필드명을 1개를 지정하면 단일 필드 인덱스, 필드명이 2개 이상이면 다중 인덱스(compound index)
인덱스에는 이 외에도 createIndex()
메소드의 두번째 파라미터로 속성을 추가 가능
db.collection_name.createIndex({<필드명>:1}, {<속성 property>:true})
db.members.createIndex( { "user_id": 1 }, { unique: true } )
db.restauratns.createIndex({"cuisine":1, "name":1}, {partialFilterExpression:{ rating: {$gt:4}}})
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )
db.collection_name.getIndexes()
db.collection_name.dropIndex(name)
db.collection_name.dropIndex({<field>:1})
db.collection_name.dropIndexes()