Mongoose

김무연·2023년 12월 20일

Backend

목록 보기
49/49
post-thumbnail

몽구스 ODM

몽고디비 작업을 쉽게 할 수 있도록 도와주는 라이브러리

  • ODM: Object Document Mapping: 객체와 다큐먼트를 매핑 (1대1 짝지음)
  • 몽고디비 자체가 js언어인데 ODM을 쓰는 이유
  • 몽고디비에 없어 불편한 기능들을 몽구스가 보완 해줌
  • 테이블과 유사한 기능, JOIN, 쿼리 빌더, SET오류 방지 등 기능 추가
  • sequelize에서는 models를 만들었다면, mongoose에서는 schemas 로 부름

몽고디비 연결

const connect = () => {
  if (process.env.NODE_ENV !== 'production') {
    mongoose.set('debug', true);
  }
  mongoose.connect('mongodb://ID이름:비밀번호이름@localhost:27017/로그인을하기위한DB이름', {
    dbName: 'DB이름',
    useNewUrlParser: true,
  }).then(() => {
    console.log("몽고디비 연결 성공");
  }).catch((err) => {
    console.error("몽고디비 연결 에러", err);
  });
};

mongoose.connect
('mongodb://ID이름:비밀번호이름@localhost:27017/로그인을하기위한DB이름',
{
dbName: 'DB이름',
useNewUrlParser: true
})

  • schemas/index.js의 함수가 실행됨
  • mongoose.connect 함수가 몽고디비에 연결을 시도
  • mongoose.set은 디버깅 모드(모드를 켰을 때 콘솔에 쿼리가 찍힘)
  • 연결이 끊기면(disconnection) 다시 연결을 시도
const mongoose = require('mongoose');

const connect = () => {
  if (process.env.NODE_ENV !== 'production') {
    mongoose.set('debug', true);
  }
  mongoose.connect('mongodb://ID이름:비밀번호이름@localhost:27017/로그인을하기위한DB이름', {
    dbName: 'DB이름',
    useNewUrlParser: true,
  }).then(() => {
    console.log("몽고디비 연결 성공");
  }).catch((err) => {
    console.error("몽고디비 연결 에러", err);
  });
};

mongoose.connection.on('error', (error) => {
  console.error('몽고디비 연결 에러', error);
});
mongoose.connection.on('disconnected', () => {
  console.error('몽고디비 연결이 끊겼습니다. 연결을 재시도합니다.');
  connect();
});

module.exports = connect;

스키마 (sequel에서는 모델) 정의

schemas 폴더 안에 작성

  • MySQL의 테이블처럼 정해진 데이터만 들어갈 수 있게 강제함
  • type은 자료형, require는 필수 여부 default는 기본값, unique는 고유 여부
  • 확장성, 자유로움 등이 몽고db의 장점인데, 스키마로 데이터를 강제시키는게 좀 아이러니 함
// schemas/users.js

const mongoose = require('mongoose');

const { Schema } = mongoose;
const userSchema = new Schema({
  name: {
    type: String,
    required: true,
    unique: true,
  },
  age: {
    type: Number,
    required: true,
  },
  married: {
    type: Boolean,
    required: true,
  },
  comment: String,
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

module.exports = mongoose.model('User', userSchema);
// schema/comment.js

const commentSchema = new Schema({
  commenter: {
    type: ObjectId,
    required: true,
    ref: 'User',
  },
  comment: {
    type: String,
    required: true,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

기존의 mongoDB에는 join기능이 없는데 mongoose에는 위처럼 ref로 어떠한 schema를 참조하는지 선언 해주고,

router.post('/', async (req, res, next) => {
  try {
    const comment = await Comment.create({
      commenter: req.body.id,
      comment: req.body.comment,
    });
    console.log(comment);
    const result = await Comment.populate(comment, { path: 'commenter' });
    res.status(201).json(result);
  } catch (err) {
    console.error(err);
    next(err);
  }
});

router에서 comment스키마가 호출될 때 populate 를 이용해 JOIN의 기능을 내준다.

문제점

populate로 join의 기능을 이용할 시, 중복도 사라지고, 변경이 바로 반영이 된다는 장점이 있지만, js문법이기 때문에 cost가 많이 들게 된다.

따라서 ObjectId로 id를 선언해주고, 직접 관계id에 객체로 데이터를 넣어줄 시, 직접 수정해야 하고, 기입해야한다는 단점이 있지만, cost가 매우 적게 든다.

때문에 서비스 특성에 따라서 알맞은 것을 쓰면 됨

profile
Notion에 정리된 공부한 글을 옮겨오는 중입니다... (진행중)

0개의 댓글