[7주차] Node.js와 MongoDB 2 - MongoDB와 Mongoose

minLuna·2023년 4월 16일
0

엘리스 AI트랙 7기

목록 보기
45/62

본 자료는 Elice 플랫폼의 자료를 사용하여 정리하였습니다.

MongoDB

MongoDB란?

  • 대표적인 NoSQL, Document DB
  • Mongo는 Humongous에서 따온 말로, 엄청나게 큰 DB라는 의미
    \rarr 대용량 데이터를 처리하기 좋다.

RDB와 NoSQL

RDB

  • Relational DataBase 관계형 데이터베이스
  • 자료들의 관계를 주요하게 다룬다.
  • SQL 질의어를 사용하기 위해 데이터를 구조화해야한다.

NoSQL을 사용하는 이유

  • 스키마에 정의된 데이터가 아니면 저장할 수 없는 제약이 따른다.
  • NoSQL은 사전작업 없이 데이터베이스를 사용할 수 있다.

MongoDB 기본개념

Database \rarr Collection \rarr Document

Database

  • 하나 이상의 Collection을 가질 수 있는 저장소
  • SQL에서의 database와 유사하다.

Collection

  • 하나 이상의 Document가 저장되는 공간
  • SQL에서의 table과 유사하다.
  • 하지만, Collection이 Document의 구조를 정의하지 않는다.

Document

  • MongoDB에 저장되는 자료
  • SQL에서 row와 유사하지만 구조제약 없이 유연하게 저장가능
  • JSON과 유사한, BSON을 사용하여 다양한 자료형을 지원
  • objectID
    • 각 Document의 유일한 키값, SQL의 primary key와 유사하다.
    • Document 생성 시 자동으로 생성되는 값이다. (timestamp + random value + auto increment)

MongoDB 사용방법

  • MongoDB
  • MongoDB Cloud
  • MongoDB Compass (GUI로 DB설정 가능)

Mongoose ODM

Mongoose ODM이란?

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

Mongoose ODM을 사용하는 이유

  • 연결관리
    • MongoDB의 기본 Node.js 드라이버는 연결상태를 관리하기 어렵다.
    • Mongoose를 사용하면 간단하게 데이터베이스와의 연결상태를 관리해준다.
  • 스키마관리
    • 스키마 정의가 필요없는건 NoSQL의 장점이지만, 데이터 형식을 미리 정의해야 코드작성과 프로젝트 관리에 유용하다.
    • Mongoose는 Code-Level에서 스키마를 정의하고 관리할 수 있게 해준다.
  • Populate
    • MongoDB는 기본적으로 Join을 제공하지 않는다.
    • Join과 유사한 기능을 사용하려면 aggregate라는 복잡한 쿼리를 해야 하지만, Mongoose는 populate를 사용하여 간단하게 구현할 수 있다.

Mongoose ODM 사용하기

스키마 정의하기

  • Code-Level에서 관리가능
  • 형식을 미리 지정하고 체크가 가능하다.
  • timestamps 옵션을 사용하면 생성, 수정시간을 자동으로 기록해준다.
const { Schema } = require('mongoose');
const PostSchema = new Schema({
  title: String,
  content: String,
}, {
  timestamps: true,
});
module.exports = PortSchema;

모델 만들기

  • 스키마를 사용할 수 있는 모델로 만들어야한다.
  • 모델의 이름을 지정할 수 있다.
const mongoose = require('mongoose');
const PostSchema = require('./schema/board');
exports.Post = mongoose.model('Post', PostSchema);

데이터베이스 연결하기

  • connect 함수를 이용하여 간단하게 데이터베이스에 연결할 수 있다.
  • mongoose는 자동으로 연결을 관리해주어 직접 연결 상태를 체크하지 않아도 모델사용 시 연결 상태를 확인하여 사용이 가능할 때 작업을 실행한다.
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/myapp');

모델 사용하기 - 간단한 CRUD

  • CREATE - Create
  • READ - find, findById, findOne
  • UPDATE - updateOne, updateMany, findByIdAndUpdate, findOneAndUpdate
  • DELETE - deleteOne, deleteMany, findByIdAndDelete, findOneAndDelete

CREATE

  • Document를 생성하고 반환해준다.
const { Post } = require('./models');

async function main() {
  const created = await Post.create({
    title: 'first title',
    content: 'second title',
  });
  
  const multipleCreated = await Post.create([
    item1,
    item2
  ]);
}

FIND (READ)

  • query를 사용하여 검색하거나 findById를 사용하면 Document를 검색할 수 있다.
const { Post } = require('./models');

async function main() {
  const listPost = await Post.find(query);
  const onePost = await Post.findOne(query);
  const postById = await Post.findById(id);
}

UPDATE

  • update~ 함수의 경우 수정 결과를 반환해준다.
  • find~ 함수의 경우 검색된 Document에 업데이트를 반영하여 반환해준다.
async function main() {
  const updateResult = await Post.updateOne(query, {
    ...
  });
  const updateResults = await Post.updateMany(query, {
    ...
  });
  const postById = await Post.findByIdAndUpdate(id, {
    ...
  });
  const onePost = await Post.findOneAndUpdate(query, {
    ...
  });

DELETE

  • delete~ 함수의 경우 삭제 결과를 반환해준다.
  • find~ 함수의 경우 검색된 Document에 삭제를 반영하여 반환해준다.
async function main() {
  const deleteResult = await Post.deleteOne(query);
  
  const deleteResults = await Post.deleteMany(query);
  
  const onePost = await Post.findOneAndDelete(query);
  
  const postById = await Post.findByIdAndDelete(query);
}

populate

  • Document 안에 Document를 담지 않고, ObjectID를 가지고 reference하여 사용할 수 있는 방법을 제공한다.
  • Document에는 reference되는 ObjectID를 담고, 사용할 때 populate하여 하위 Document처럼 사용할 수 있게 해준다.
const Post = new Schema({
  ...
  user: {
    type: Schema.Types.ObjectId,
    ref: 'User'
  },
  comments: [{
    type: Schema.Types.ObjectId,
    ref: 'Comment',
  }],
});

const post = await Post.find().populate(['user', 'comments']);

// post.user.name, post.comments[0].content

자주 사용되는 query

  • {key: value}로 exact match
  • $lt, $lte, $gt, $gte를 사용하여 range query 작성 가능
  • $in을 사용하여 다중 값으로 검색
  • $or을 사용하여 다중 조건 검색
Person.find({
  name: 'kyubum',
  age: {
    $lt: 20,
    $gte: 10,
  },
  languages: {
    $in: ['ko', 'en'],
  },
  $or: [
    { statue: 'ACTIVE' },
    { isFresh: true },
  ],
});

Express.js + Mongoose ODM

Mongoose ODM 커넥션 이벤트

  • connected - 연결 완료
  • disconnected - 연결이 끊김
  • reconnected - 재연결 완료
  • reconnecteFailed - 재연결 시도 횟수 초과
mongoose.connect('----');

mongoose.connection.on('connected', () => {
});

mongoose.connection.on('disconnected', () => {
});

mongoose.connection.on('reconnected', () => {
});

mongoose.connection.on('reconnecteFailed', () => {
});
profile
열심히

0개의 댓글