우리는 이제 Many-to-Many와 One-to-Many 관계를 쓰임에 따라 비교할 수 있는데, 그 결론으로 "Super Many-to-Many relationship"의 개념에 다다른다.
우리가 만약 시퀄라이즈로 User
와 Profile
이 Grant
라는 through table을 통해 Many-to-Many relationship을 만들려면 다음과 같이 사용하면 된다.
User.belongsToMany(Profile, { through: Grant });
Profile.belongsToMany(User, { through: Grant });
이 코드는 자동으로 Grant
라는 테이블에 userId
와 profileId
라는 컬럼을 추가해준다.
내가 궁금했던 것이다.
위의 다대다 관계로 정의하는 대신에 다음처럼 한다면 어떻게 될까?
// Setup a One-to-Many relationship between User and Grant
User.hasMany(Grant);
Grant.belongsTo(User);
// Also setup a One-to-Many relationship between Profile and Grant
Profile.hasMany(Grant);
Grant.belongsTo(Profile);
결과는 같다!
이 코드에서도, User.hasMany(Grant)
와 Profile.hasMany(Grant)
가 Grant
에 자동으로 userId
, profileId
컬럼을 추가하기 때문이다.
This shows that one Many-to-Many relationship isn't very different from two One-to-Many relationships. The tables in the database look the same.
유일한 차이점은: 시퀄라이즈로 eager load를 수행할 때
// you can do:
User.findAll({ include: Profile });
Profile.findAll({ include: User });
// However, you can't do:
User.findAll({ include: Grant });
Profile.findAll({ include: Grant });
Grant.findAll({ include: User });
Grant.findAll({ include: Profile });
// you can do:
User.findAll({ include: Grant });
Profile.findAll({ include: Grant });
Grant.findAll({ include: User });
Grant.findAll({ include: Profile });
// However, you can't do:
User.findAll({ include: Profile });
Profile.findAll({ include: User });
// Although you can emulate those with nested includes, as follows:
User.findAll({
include: {
model: Grant,
include: Profile
}
});
// 근데 이건 너무 불편했었다.
그래서 가장 좋은 방법은,, 바로
우리는 단순히 두가지 접근 방법을 다음과 같이 합칠 수 있다.
// The Super Many-to-Many relationship
User.belongsToMany(Profile, { through: Grant });
Profile.belongsToMany(User, { through: Grant });
User.hasMany(Grant);
Grant.belongsTo(User);
Profile.hasMany(Grant);
Grant.belongsTo(Profile);
이 방법으로 우리는 다음의 모든의 eager loading을 가능하기 할 수 있다.
// All these work:
User.findAll({ include: Profile });
Profile.findAll({ include: User });
User.findAll({ include: Grant });
Profile.findAll({ include: Grant });
Grant.findAll({ include: User });
Grant.findAll({ include: Profile });
이런식으로 deeply nested includes도 사용 가능하다 😀
User.findAll({
include: [
{
model: Grant,
include: [User, Profile]
},
{
model: Profile,
include: {
model: User,
include: {
model: Grant,
include: [User, Profile]
}
}
}
]
});
출처 : 시퀄라이즈 api reference