Elice SW 2/TIL

DAY 29 - TIL

자이구 2022. 5. 15. 01:16

MongoDB

  • 대표적인 NoSQL, Document DB
  • 구조화된 질의어를 사용하지 않은 데이터베이스
  • 자료 간의 관계에 초점을 두지 않음
  • 데이터를 구조화하지 않고, 유연하게 저장 -> 프로젝트를 빠르게 진행
  • 대용량 데이터를 처리하기 좋게 만들어짐
  • NoSQL은 Document DB가 일반적이며, key-value,Graph,large collection 등의 No SQL DB존재

Database

하나 이상의 collection 을 가질 수 있는 저장소

 

Collection

하나 이상의 Document가 저장되는 공간

collection이 document의 구조를 정의하지 않음

 

Documnet

MongoDB에 저장되는 자료

JSON과 유사한,BSON을 사용하여 다양한 자료형을 지원

 

ObjectID

각 document의 유일한 키 값

document를 생성할 때 자동으로 생성되는 값 timestamp + random value + auto increase

 

MongoDB ODM

  • Object Data Modeling
  • MongoDB의 Collection에 집중하여 관리하도록 도와주는 패키지
  • Collection을 모델화하여, 관련 기능들을 쉽게 사용할 수 잇도록 도와줌

연결관리

MongoDB의 기본 Node.js 드라이버는 연결상태를 관리하기 어려움

Mongoose를 사용하면 간단하게 DB와의 연결상태를 관리

 

스키마 관리

스키마를 정의하지 않고 데이터를 사용하는것이 NoSQL의 장점

데이터 형식을 미리 정의 해야 코드 작성과 프로젝트 관리에 유용

Mongoose는 Code-Level에서 스키마를 정의하고 관리할 수 있게 해줌

 

Populate

MongoDB의 기본적으로 Join을 제공하지 않음

Join과 유사한 기능을 사용하기 위해서 aggregate라는 복잡한 쿼리를 해야 하지만,

Mongoose는 populate를 사용하여 간단하게 구현할 수 있음

 

Mongoose ODM 사용 순서

  1. 스키마 정의
  2. 모델 만들기
  3. 데이터 베이스 연결
  4. 모델 사용

 

스키마 정의

  • collection에 지정될 Document의 스키마를 Code-Level에서 관리할 수 있도록 Schema를 작성
  • 다양한 형식을 미리 지정하여, 생성/수정 작업 시 데이터 형힉을 체크해 주는 기능을 제공
  • timestamps 옵션을 사용하면 생성/수정 시간을 자동으로 기록
const mongoose = require('mongoose');
const autoIncrement = require('mongoose-auto-increment');
const Schema = mongoose.Schema;

//반드시 초기화
autoIncrement.initialize(mongoose);

const blogSchema = new Schema({
    title: {
      type: String,
      required : true
    },
    content: {
        type: String,
      required : true
    },
    no:{
        type:Number
    }
},{
    timestamps:true
});

blogSchema.plugin(autoIncrement.plugin,{
    model:'blog',
    field: 'no',
    startAt: 4,
    increment:1
})

module.exports = blogSchema;

auto - increment 

  1.  npm install Mongoose-auto-increment 설치
  2.  auto-increment를 require 해준 후 연결된 Mongoose connection을 이용하여 초기화
  3.  DB 스키마에 필드를 추가(type:Number)
  4. 스키마를 생성한 후 다음 코드를 추가
  5. auto-increment 스키마 매핑 

 

모델 만들기

  • 작성된 스키마를 mongoose에서 사용할 수 있는 모델로 만듦
  • 모델의 이름을 지정하여 해당 이름으로 모델을 호출할 수 있음
mongoose.model(<컬렉션 이름>, <컬렉션 스키마>)
const mongoose = require('mongoose');
cosst blogSchema = require('./Schema/blog');

exports.Blog = mongoose.model('Blog',blogSchema);

 

데이터베이스 연결

  • connect 함수를 이용하여 간단하게 DB에 연결
  • mongoose는 자동으로 연결을 관리하여 직접 연결 상태를 체크하지 않아도 모델 사용 시 연결 상태를 확인하여 사용이 가능할 때 작업을 실행(비동기 실행)
  • 작성된 모델을 이용하여 CRUD를 수행 가능
const express = require('express')
const router = express.Router();
const blogSchema = require('../models/blog')
 
router.get('/', async(req,res)=>{
    const result = await blogSchema.find({}).exec();
    res.render('blog/blog',{content:result});
});

router.get('/')

router.get('/write',(req,res)=>{
    res.render('blog/write');
});

router.post('/write',(req,res)=>{
    const title = req.body.title;
    const content = req.body.content;
    
    const blogText = new blogSchema({
        title:title,
        content:content,
    });

    blogText.save().then(result => {
        console.log(result);
        res.redirect('/blog');
    }).catch(err=>{
        console.log(err);
        next(err);
    });
});

module.exports = router;

 

populate

  • Document 안에 Document를 담지 않고, ObjectId를 가지고 reference하여 사용할 수 있는 방법을 제공
  • Document에서 reference되는 ObjectId를 담고, 사용할 때 populate하여 하위 Document처럼 사용할 수 있게 해줌

 

Express.js ODM

  • Express.js는 프로젝트 구조를 자유롭게 구성
  • 어느 부분에 Mongoose ODM을 위치시키면 좋을지 적절한 위치를 결정하는 것이 중요
  • 일반적으로 models 디렉터리에 Schema와 Model을 같이 위치
  • app 객체는 어플리케이션 시작을 의미하는 부분으로 해당부분에 DB 연결을 명시하는 mongoose.connect를 위치
  • Express.js 어플리케이션은 종료되지 않고 동작하기 때문에 계속해서 DB가 정상적으로 동작하는지를 파악하기 위해 동작 중에 발생하는 DB 연결 관련 이벤트에 대한 처리를 하는 것이 좋음

 

connected - 연결완료

disconnected  - 연결이 끊김

reconnected - 재연결 완료

reconnectedFailed - 재연결 시도 횟수 초과

 

Sequelize ORM

  • object - Relational Mapping
  • RDBMS를 이용하는 간단한 방법
  • ODB이 모델에 집중하여 관리하는 것에 반해, ORM은 테이블 관계와 쿼리 등의 기능을 더욱 단순화하는 용도
  • Sequelize ORM 을 사용하면 데이터베이스에 직접 DDL을 하지 않고 JavaScript 코드로 테이블 및 관계를 관리
  • RDB의 어려운 점 중 하나인 join을 간단하게 사용

디비 연결

sequelize도 연결을 관리하는 간단한 방법을 제공함으로써 다양한 RDBMS에 연결 가능

const sequelize = new Sequelize('database', 'username', 'password', {
	host: 'localhost',
	dialect: 'mysql'
});

 

스키마 작성

define을 통해 Schema를 생성 

mongoose.Schema와 유사하지만 DDL도 생성해줌

const User = sequelize.define('User', {
	name: {
		type: DataTypes.STRING(10),
		allowNull: false
	},
	age: {
		type: DataTypes.Integer,
	}
}, {});

 

스키마 작성 - 관계정의

sequelize를 이용하면 테이블 간의 관계를 Code-Level로 관리

외래키 설정과 제약조건까지 DDL로 생성

다대다 관계 설정을 통해 relation table도 자동으로 생성

User.hasMany(Post);
Post.belongsTo(User);
Foo.belongsToMany(Bar);
Bar.belongsToMany(Foo);

 

쿼리

Operator를 이용해 SQL 쿼리를 코드로 작성 가능

스키마의 관계 설정을 한 경우,  include를 사용하여 자동으로 join 쿼리 생성 가능

User.findAll({
	where: {
		name: 'elice',
		age: {
			[Op.lt]: 20,
			[Op.gte]: 10,
		}, 
	},
	include: User,
});

 

Synchronization

define된 model 데이터를 바탕으로 DDL을 자동으로 실행

직접 DB에 접속하여 테이블 생성 및 관리 필요 X

자동으로 생성된 DDL을 따르지 않으면 테이블 관리가 어려워 짐

sequelize.sync();