일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Vue
- 다른컴퓨터에서 git사용
- postcss
- 고양이 사진 검색기
- vue 이벤트 수신
- Spacer
- vuex map
- git 같은계정 다른 컴퓨터
- react next
- nextjs사용법
- KDT 프로그래머스
- SCSS import
- SCSS forward
- SCSS use
- 프로그래머스 데브코스
- 이벤트 수식어
- netlify redirect
- intersection opserver
- vue mixin
- 프로그래머스 데브코스 프론트엔드
- 리스트 렌더링
- 폼 입력 바인딩
- 프로그래머스 프론트엔드 데브코스
- vue 지역 컴포넌트
- flex
- KDT 프로그래머스 데브코스 프론트엔드
- SCSS extend
- 쌓임맥락
- 프로그래머스 K_Digital Training
- 리액트
- Today
- Total
혼자 적어보는 노트
[Node.js] sequelize 관계 설정(association)하기 / 1:1 / 1:M / N:M 본문
이전 포스팅에서 모델을 정의하고 MySQL을 연결하는 것 까지 진행했었다.
데이터를 연결하면서 관계설정에 대해 알게 되었는데 약간 개념이 헷갈리게되어
예시 상황을 만들고 정리해보면서 개념을 다시 제대로 이해해보기로 했다.
독립적으로 사용하는 데이터가 있는 반면
보통 연관성이 있는 데이터가 많다.
게시판을 구현하기 위한 간단한 User, Post, Comment 세 가지의 모델끼리만 해도
User은 자신이 등록한 게시물인 Post, 자신이 작성한 Comment의 정보를 가지고 있어야하고
Post는 게시물을 등록한 User과 포스트에 달린 Comment의 정보를 가지고 있어야한다.
또한 Comment는 댓글을 단 User와 어느 포스트에 달린 댓글인지에 대한 Post의 정보를 가지고 있어야한다.
이렇게 연관성 있는 데이터끼리의 관계 설정(association)을 해주어야 한다.
assosiate
Post.associate = (db) => {
};
모델 객체에 associate 프로퍼티를 함수를 할당하고 함수 내부에 관계설정을 해주면 된다.
모델의 관계 설정 통합
models/index.js안에는 기본적으로 관계설정을 취합하는 코드가 있다.
models 폴더 안의 모델 파일들에 관계를 정의해 놓으면 index.js파일에서 관계를 통합하게된다.
models/index.js
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
* 여기서 associate(db)를 호출하는데 이 db가 Post.associate =(db) => {} 여기의 db로 가게된다.
관계설정
관계설정에는 1:1(일대일), 1:M(일대다), N:M(다대다)가 존재한다.
🙍♀️🙍♂️ 1:1(일대일)관계
예를들어 유저와 유저의 정보의 테이블이 있어서 1:1으로 매칭해야 하는 상황.
// User
User.associate = (db) => {
db.User.hasOne(db.UserInfo, {foreignKey: "userId"};
};
// UserInfo
UserInfo.associate = (db) => {
db.UserInfo.belongsTo(db.User, {foreignKey: "userId"};
};
User은 UserInfo를 하나 가질 수 있고 (hasOne)
Profile은 User에 속한다는 의미인 belongsTo()를 사용한다.
🙍♀️ 👨👩👧👧1:M(일대다) 관계
Post모델과 Comment 모델의 관계
한 게시글은 여러개의 댓글을 가질 수 있으며, 댓글은 한 게시글에 속해있다.
게시글과 댓글은 1 : M 관계이다.
models/post.js
module.exports = (sequelize, DataTypes) => {
const Post = sequelize.define(
"Post",
{
title:{
type: DataTypes.STRING(50),
allowNull: false,
}
content: {
type: DataTypes.TEXT,
allowNull: false,
},
},
);
Post.associate = (db) => {
db.Post.hasMany(db.Comment);
};
return Post;
};
1:M 관계에서는 hasMany()를 사용하고 인자로는 M이되는 모델을 작성한다.
그리고 M이되는 Comment에서도 Post와의 관계를 매핑해주어야 한다.
models/comment.js
module.exports = (sequelize, DataTypes) => {
const Comment = sequelize.define(
"Comment",
{
content: {
type: DataTypes.TEXT,
allowNull: false,
},
},
);
Comment.associate = (db) => {
db.Comment.belongsTo(db.Post, { foreignKey: "PostId"} );
};
return Comment;
};
여기서 Comment는 하나의 Post에 포함되어 있으며
이렇게 포함이 되어 있는 모델에는 belongsTo()를 사용한다.
Comment는 하나의 post안에 속해있어야 하는데
어떤 게시글(게시글이 여러개기 때문)에 포함되어 있는지 알아야 한다.
그래서 PostId라는 정보가 필요하다.
belongsTo를 사용하면 Comment의 테이블에 PostId라는 column이 생긴다.
* foreignkey는 새로 생성되는 column의 이름을 변경하는 속성이고
foreignkey를 생략해도 column이 생성되고 이름 또한 기본으로 PostId로 생성된다.
위의 개념들을 토대로 User, Post, Comment의 associate를 작성해보자.
// User
User.associate = (db) => {
db.User.hasMany(db.Post); // 여러개의 Post를 가짐
db.User.hasMany(db.Comment); // 여러개의 Comment를 가짐
};
// Post
Post.associate = (db) => {
db.Post.belongsTo(db.User); // User에 속해 있음
db.Post.hasMany(db.Comment); // 여러개의 Comment를 가짐
};
// Comment
Comment.associate = (db) => {
db.Comment.belongsTo(db.User); // User에 속해 있음
db.Comment.belongsTo(db.Post); // Post에 속해 있음
};
위와 같이 작성을 하여 관계 설정을 해주었다. *foreignKey는 생략
이렇게 되면 Post는 UserId를 가지고 있고
Comment는 UserId, PostId를 가지고 있게 된다.
👩👩👧👦👨👩👧👧 N:M(다대다) 관계
다대 다의 관계에서는 belongsToMany()를 사용한다.
belongsToMany()를 사용하면 각 테이블의 foreignKey를 공유하는 새로운 또 하나의 테이블이 생성된다.
예시 상황을 만들어보자
1. 다른 모델끼리의 N:M
: 예약시스템 중에서 하나의 유저가 여러 서비스를 예약할 수 있고
하나의 서비스가 여러 유저를 보유 할 수 있는 상황.
User.associate = (db) => {
db.User.belongsToMany(db.Service, {
through: 'UserConcert',
foreignKey: 'userId'
});
};
through는 새로 생성할 테이블의 이름을 설정할 수 있다.
Service.associate = (db) => {
db.Service.belongsToMany(db.User, {
through: 'UserConcert',
foreignKey: 'ServiceId'
});
};
위와 같이 두 모델 서로 belongsToMany(db.상대모델, {through: "중간테이블이름"}) 적어준다.
2. 같은 모델 안에서의 N:M
: 하나의 유저가 여러 유저를 팔로잉 하고 있고
하나의 유저가 여러 팔로워를 가지는 상황 (* 헷갈림주의)
User.associate = (db) => {
db.User.belongsToMany(db.User, {
through: 'follow',
as: 'followers'
foreignKey: 'followingId'
});
db.User.belongsToMany(db.User, {
through: 'follow',
as: 'followings'
foreignKey: 'followersId'
});
};
같은 모델 안에서 2개를 선언하는 방식이며
through 속성을 이용하여 새로생성되는table이름을 지정해주고
as속성을 같은 모델 안에서 구분을 할 수 있는 이름을 설정해준다.
foreignKey는 반대로 입력을 해준다.
jay가 hey와 bey를 팔로잉 하고 있다고 생각하고
테이블 구조를 그려보자 (hey와 bey는 jay 팔로잉 X)
user followings followers
1: jay 2 1
2: hey 3 1
3: Bey
여기서 jay가 팔로잉 하고 있는 사람을 찾으려면 follower를 먼저 찾아야 하는데
먼저 찾아야 하는것을 foreignKey로 설정해야한다.
📑 요약
1:1
hasOne(), belongsTo() 사용
1:M
hasMany(), belongsTo() 사용
N:M
연관된 모델 각각 belongsToMany() 사용.
foreignkey과 as는 반대로 입력
belongsTo() 사용 시 해당 모델에 Id column 생성
belongsToMany() 사용 시 연관 테이블 생성, Id column 생성
through: 새로운 테이블의 name 지정 생략 시 연관된 두 테이블이 합쳐진 이름이 생성된다. (예: UserPost)
* 같은 테이블 안에서의 새롭게 table을 생성했을 때 UserId와 UserId로 생성되기 때문에 구분을 위해 지정해야 한다.
foreignKey: 생성된 column의 name 지정, 생략 시 소속되는 모델명+Id가 생성된다. (ex: UserId)
as : 같은 모델 안에서 관계가 헷갈릴경우 as를 사용하여 별칭을 붙여준다.
참고 - https://lgphone.tistory.com/86
공식문서 - https://sequelize.org/master/manual/associations.html
'NodeJS' 카테고리의 다른 글
[Node.js] 중복 로그인 검사 미들웨어 / middleware (0) | 2022.03.21 |
---|---|
[Node.js] sequelize 연관된 데이터 합쳐서 불러오기 / attributes, include (0) | 2022.03.20 |
[Node.js] bcrypt로 암호화 (0) | 2022.03.18 |
[Node.js] NodeJS에 MySQL 연결하기 / Sequelize (0) | 2022.03.17 |
[Package] http-server / live-server (0) | 2021.12.02 |