sequelize를 사용하다 보면 하나의 필드를 어떤 상황에서는 User테이블과 조인하고 다른 상황에서는 Dept 테이블과 조인을 하고 싶을 때가 있다.

예를 들면 만약 로그를 기록 한다 하였을 때 모든 행위마다 로그를 기록할 수는 없기때문에 로그 테이블에 필드에 type을 나누고 발생한 object의 index만을 기록해서 진행하고 싶을 때 그럴 수있다.


그럴경우 targetIndex의 경우 동작 타입에 따라 User테이블과 조인할 수도 있고 Dept 테이블과 조인하는 등 유동적인 조치가 필요하다.


우선 Model을 define 하는 부분을 확인해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Pub = Sequelize.define('pub', {
  name: { type: Sequelize.STRING },
targetIdx: { type: Sequelize.INTEGER }.
  address: { type: Sequelize.STRING },
  latitude: {
    type: Sequelize.INTEGER,
    allowNull: true,
    defaultValue: null,
    validate: { min: -90, max: 90 }
  },
  longitude: {
    type: Sequelize.INTEGER,
    allowNull: true,
    defaultValue: null,
    validate: { min: -180, max: 180 }
  }
}

Pub.association = function(models) {
Pub.belongTo(models.User, {
target: 'targetIdx',
foreign: 'userId',
as: 'UserDefines'
});
Pub.belongTo(models.Dept, {
target: 'targetIdx',
foreign: 'deptId',
as: 'DeptDefines'
});
};
cs


모델을 define할때 조인이 필요한 테이블과의 관계를 미리 설정을 해둬야한다. alias를 미리 설정해줘야 필요에 따라 조인하고 싶은 연결 조건을 가져다 쓸 수 있다. 물론 별칭을 정의 하지 않으면 모델명 그 자체 이름으로 자동지정된다.


쿼리 사용 부분

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Dept 테이블과 조인할 때
await This.Pub.findOne({
  attributes: [['name', 'userName'], 'targetIdx'],
  include: [
    { 
        model: this.Dept, 
        required: false
        as: 'DeptDefines'
    }
  ]
});
 
// 사용자 테이블과 조인할 때
await This.Pub.findOne({
  attributes: [['name', 'userName'], 'targetIdx'],
  include: [
    { 
        model: this.User, 
        required: false
        as: 'UserDefines'
    }
  ]
});
cs


필요한 부분에 정확하게 as를 지엉해주고 model에 조인하고 싶은 테이블을 필요에 따라 지정해주면 된다. 이때 연관관계가 만들어지면 안되기 때문에 define시에 constraint옵션을 false로 지정하고 하면 더욱 좋다.


sequelize ORM이 점점 익숙해져간다.

+ Recent posts