728x90
Sequelize
SQL 작없을 쉽게 할 수 있도록 도와주는 라이브러리
- ORM(Object Relational Mapping): 객체와 데이터를 맵핑(1 : 1 짝지음)
- mySQL 외에도 다른 RDB(Maria, Postgre, SQLite, MSSQL)와도 호환됨
- 자바스크립트 문법으로 데이터베이스 조작 가능
Sequelize-cli 사용하기 위한 명령어
% npm i express morgan nunjucks sequlize sequelize-cli mysql2
→ mysql2는 MySQL DB가 아닌 드라이버(Node.js와 MySQL을 이어주는 역할)
% npm i -D nodemon
% npx sequelize init → sequelize 구조 생성
MySQL과 Sequelize의 비교
MySQL | Sequelize |
VARCHAR(100) | STRING(100) |
INT | INTEGER |
TINYINT | BOOLEAN |
DATETIME | DATE |
INT UNSIGNED | INTEGER.UNSIGNED |
NOT NULL | allowNull: false |
UNIQUE | unique: true |
DEFAULT now() | defaultValue: Sequelize.NOW |
define 메서드의 세번째 인자는 테이블 옵션
- timestamp: true면 createdAt(생성 시간), updatedAt(수정 시간) 컬럼을 자동으로 만듦
- paranoid 옵션은 true면 deletedAt(삭제 시간) 컬럼을 만듦., 로우 복구를 위해 완전히 삭제하지 않고 deletedAt에 표시해둠
- underscored 옵션은 캐멀 케이스로 생성되는 컬럼을 스네이크 케이스로 생성
- modelName은 모델 이름, tableName 옵션은 테이블 이름을 설정
- charset과 collate는 한글 설정을 위해 필요(이모티콘 넣으려면 utf8mb4로)
테이블 관계 이해하기
users 모델과 comments 모델 간의 관계를 정의 / 1 대 N
- 1:N 관계 (사용자 한 명이 댓글 여러 개 작성 → 댓글 하나에 사용자가 여러명일 수 없음)
- sequelize에서는 1:N 관계를 hasMany로 표현(사용자.hasMany(댓글))
- 반대의 입장에서는 belongsTo(댓글.belongsTo(사용자))
- belongsTo가 있는 테이블에 컬럼이 생김(댓글 테이블에 commenter 컬럼)
1 대 1 관계
ex) 사용자 테이블과 사용자 정보 테이블
db.User.hasOne(db.Info, { foreignKey: 'UserId', sourceKey: 'id' });
db.Info.belongsTo(db.User, { foreignKey: 'UserId', targetKey: 'id' });
다대다 관계
ex) 게시글과 해시태그 테이블 하나의 게시글이 여러개의 해시태그를 가질 수 있고 하나의 해시태그가 여러개의 게시글을 가질 수 있다.
DB 특성상 다대다 관계는 중간 테이블이 생김
db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag' });
db.Hashtag.belongsToMany(db.Post, { through: 'PostHashtag' });
N:M 관계 테이블
- 한 컬럼에 하나만 있어야 하기 때문에(정규화 원칙) 다대다 관계가 생긴다면 중간 테이블이 존재해야한다.
- 중간 테이블이 존재하지 않는다면 정규화 원칙에 어긋난다.
SQL문과 Sequelize 쿼리의 차이
Create
INSERT INTO nodejs.users (name, age, married, comment)
VALUES ('zero', 24, 0, '자기소개1');
const { User } = require('../models');
User.create({
name: 'zero',
age: 24,
married: false,
comment: '자기소개1',
});
Reade
SELECT * FROM nodejs.users;
User.findAll({});
SELECT name, married From nodejs.users;
User.findAll({
attributes: ['name', 'married']
});
특수한 기능들인 경우 Sequelize.Op의 연산자 사용(gt, or등)
gt >, lt <, gte >=, lte <=, in [a,b,c]
SELECT name, age FROM nodejs.users
WHERE married = 1 AND age > 30;
const { Op } = require('sequelize');
const { User } = require('../models');
User.findAll({
attributes: ['name', 'age'],
where: {
married: true,
age: {[Op.gt]: 30},
},
});
SELECT id, name FROM users WHERE married = 0 OR age > 30;
const { Op } = require('sequelize');
const { User } = require('../models');
User.findAll({
attributes: ['id', 'name'],
where: {
[Op.or]: [{married: false}, {age: {[Op.gt]: 30}],
},
});
SELECT id, name FROM users ORDER BY age DESC;
User.findAll({
attributes: ['id', 'name'],
// 2차원 배열 [['age', 'DESC'], [createdAt, 'asc']]
order: [['age', 'DESC']]
});
SELECT id, name FROM users ORDER BY age DESC LIMIT 1;
User.findAll({
attributes: ['id', 'name'],
order: [['age', 'DESC']],
limit: 1,
});
SELECT id, name FROM users ORDER BY age DESC LIMIT 1 OFFSET 1;
User.findAll({
attributes: ['id', 'name'],
order: [['age', 'DESC']],
limit: 1,
offset: 1,
});
UPDATE
UPDATE nodejs.users SET comment = '변경 내용' WHERE id = 2;
User.update({
comment: '변경 내용',
}, {
where: { id: 2 },
});
DELETE
DELETE FROM nodejs.users WHERE id = 2;
User.destory({
where: { id: 2 },
});
User.destory({
// in 활용하여 1,3,5 아이디 지우기
where: { id: {[Op.in]: [1, 3, 5]} },
});
User.destory({
// ne 활용하여 5를 제외한 나머지 아이디 지우기
where: { id: {[Op.ne]: 5} },
});
관계 쿼리
결과값이 자바스크립트 객체일 때
const user = await User.findOne({});
console.log(user.nick); // 사용자 닉네임
include로 join과 비슷한 기능 수행(관계 있는 것 엮기)
const user = await User.findOne({
include: [{
model: Comment,
}]
});
console.log(user.Comments); // 사용자 댓글
// 사용자 가져오는 동시에 댓글도 가져오기 때문에 성능에 문제있을 수 있음
include나 관계 쿼리 메서드에서도 where나 attributes
const user = await User.findOne({
include: [{
model: Comment,
where: {
id: 1,
},
attributes:['id'],
}]
});
// OR
const comments = await user.getComments({
where: {
id: 1,
},
attributes: ['id'];
})
console.log(user.Comments); // 사용자 댓글
다대다 모델은 다음과 같이 접근
db.sequelize.models.PostHashtag
get+모델명으로 관계 있는 데이터 로딩 가능
const user = await User.findOne({});
const comments = await user.getComments();
console.log(comments); // user 사용자 댓글
as로 모델명 변경 가능
// 관계 설정 시 as로 등록
db.User.hasMany(db.Comment, {
foreignKey: 'commenter', sourceKey: 'id', as: 'Answers' });
// 쿼리는
const user = await User.findOne({});
const comments = await user.getAnswers();
console.log(comments); // 사용자 댓글
생성 쿼리
const user = await User.findOne({});
const comment = await Comment.create();
await user.addComment(comment);
// OR
await user.addComment(comment.id);
여러 개를 추가할 때는 배열로 저장
const user = await User.findOne({});
const comment1 = await Comment.create();
const comment2 = await Comment.create();
await user.addComment([comment1, comment2]);
수정은 set+모델명, 삭제는 remove+모델명
직접 SQL문 작성 가능
const [result, metadate] =
await sequelize.query('SELECT * from comments');
console.log(result);
728x90
'IT > Node.js' 카테고리의 다른 글
[Node.js] 버전 업데이트 (0) | 2024.01.09 |
---|---|
Node.js (0) | 2021.12.12 |
Node.js - Middleware/Jest (0) | 2021.12.06 |
Node.js - ORM/Sequelize (0) | 2021.11.28 |
Node.js - Restful API/package json (0) | 2021.11.22 |