M x N association table 컬럼 추가 및 수정

broccoli·2021년 7월 13일
0

sequelize

목록 보기
7/7
post-thumbnail

컬럼추가한 association through table 참조하기

M x N Association Table에는 기본적으로 참조한 모델의 기본키만 컬럼으로 들어가는데, 추가적으로 컬럼을 넣고 싶다면 모델을 만들어서 만든 모델을 through로 추가하면 된다.

If you want additional attributes in your join table, you can define a model for the join table in sequelize, before you define the association, and then tell sequelize that it should use that model for joining, instead of creating a new one:

// 참고소스
User = sequelize.define('user', {})
Project = sequelize.define('project', {})
UserProjects = sequelize.define('userProjects', {
    status: DataTypes.STRING
})
 
User.belongsToMany(Project, { through: UserProjects })
Project.belongsToMany(User, { through: UserProjects })

위에 소소는 참고링크에 나와 있는 예이고 아래 예는 내가 실제로 사용한 소스이다.

// 실제 사용 예
// Posthashtag 모델을 참고할 예정
const DataTypes = require('sequelize')

const { Model } = DataTypes

module.exports = class Posthashtag extends Model {
  static init(sequelize) {
    return super.init(
      {
        isUse: {
          type: DataTypes.BOOLEAN,
          allowNull: false,
          defaultValue: true
        },
        isTemp: {
          type: DataTypes.BOOLEAN,
          allowNull: false,
          defaultValue: false
        },
        isTempDeleted: {
          type: DataTypes.BOOLEAN,
          allowNull: false,
          defaultValue: false
        }
      },
      {
        modelName: 'Posthashtag',
        tableName: 'posthashtags',
        charset: 'utf8mb4',
        collate: 'utf8mb4_general_ci',
        sequelize
      }
    )
  }
}

// Post 모델
const DataTypes = require('sequelize')

const { Model } = DataTypes

module.exports = class Post extends Model {
  static init(sequelize) {
    return super.init(
      {
     ...
      },
      {
        modelName: 'Post',
        tableName: 'posts',
        charset: 'utf8mb4',
        collate: 'utf8mb4_general_ci',
        sequelize
      }
    )
  }

  static associate(db) {
    ...
    db.Post.belongsToMany(db.Hashtag, {
      through: db.Posthashtag,
      onUpdate: 'CASCADE',
      onDelete: 'CASCADE',
      foreignKey: 'postId',
      sourceKey: 'id'
    })
  }
}


// Hash tag 모델
const DataTypes = require('sequelize')

const { Model } = DataTypes

module.exports = class Hashtag extends Model {
  static init(sequelize) {
    return super.init(
      {
        tag: {
          type: DataTypes.STRING(20),
          allowNull: false
        }
      },
      {
        modelName: 'Hashtag',
        tableName: 'hashtags',
        charset: 'utf8mb4',
        collate: 'utf8mb4_general_ci',
        sequelize
      }
    )
  }

  static associate(db) {
    db.Hashtag.belongsToMany(db.Post, {
      through: db.Posthashtag,
      onUpdate: 'CASCADE',
      onDelete: 'CASCADE',
      foreignKey: 'hashtagId',
      sourceKey: 'id'
    })
  }
}

// index.js
const env = process.env.NODE_ENV || 'development'
const Sequelize = require('sequelize')
const post = require('./post')
const hashtag = require('./hashtag')
const posthashtag = require('./posthashtag')

const config = require('../config/config')[env]

const db = {}

const sequelize = new Sequelize(
  config.database,
  config.username,
  config.password,
  config
)

db.Posthashtag = posthashtag
db.Hashtag = hashtag
db.Post = post

Object.keys(db).forEach((modelName) => {
  db[modelName].init(sequelize)
})

Object.keys(db).forEach((modelName) => {
  if (db[modelName].associate) {
    db[modelName].associate(db)
  }
})

db.sequelize = sequelize
db.Sequelize = Sequelize

module.exports = db

through 테이블 컬럼값 수정하기

M x N 관계에서는 sequelize에서 제공한 add,set,remove,has,count,get, create 함수를 사용할 수 있다. 관련 정보는 BelongsToMany링크를 참조하면 됨.

이번에 간단히 작성할 예제는 위에서 언급한데로 참조한 기본키값이 아닌 다른 값을 수정할 경우에 사용하는 방법이다.

throught 테이블이 만약 기본키들만 가지고 있는게 아니라 추가로 다른 컬럼을 가지고 있는 모델일 경우 아래와 같이 수정하거나 생성하거나 할 수 있다.

// tag: Hashtag 모델의 instance임.
// Post, Posthashtag (through 테이블 모델: Post x Hashtag)
 const isExist = await tag.hasPost(post)
 let addedTag = null
 if (!isExist) {
   addedTag = await tag.addPost(post, {
     through: { isTemp: false, isUse: true }
   })
 } else {
   addedTag = await Posthashtag.update(
     { isTemp: false, isTempDeleted: false, isUse: true },
     {
       where: { postId: post.id, hashtagId: tag.id }
     }
   )
 }

여기서 has함수를 통해서 이미 연결된 데이터인지 확인하는 이유는 이미 연결된 정보의 경우는 추가 연결이 되지 않음. 즉 수정 안되기 때문. 따라서 연결이 안된 경우는 add를 통해서 연결을 해주고 이미 연결된 경우에는 해당 모델을 직접 참조해서 update 함수를 사용한다.

참고링크

profile
🌃브로콜리한 개발자🌟

0개의 댓글