데이터베이스

Sequelize 1:N associate

realtrynna 2022. 5. 5. 19:36

Sequelize 1:N associate

JOIN 기능을 구현하기 위해 시퀄라이즈 모델 간의 관계를 설정하기 위한 메서드이다.

 

폴더 구조

 

1:N

유저 모델과 유저가 작성한 게시글 모델 간의 일대다 관계

- 유저 한 명은 게시글을 여러 개 작성할 수 있다.

- 게시글 하나는 한 명의 사용자만 갖는다.

- 유저 모델 hasMany/sourceKey 게시글 모델 belongsTo/targetKey

- belongsTo를 사용하는 모델에 UserId 컬럼이 추가된다.

 

const Sequelize = require("sequelize");

module.exports = class User extends Sequelize.Model {
  static init(sequelize) {
    return super.init({
      email: {
        type: Sequelize.STRING(100),
        allowNull: false,
        unique: true,
      },
      password: {
        type: Sequelize.STRING(200),
        allowNull: false,
      },
      name: {
        type: Sequelize.STRING(10),
        allowNull: false,
      },
      age: {
        type: Sequelize.INTEGER.UNSIGNED,
        allowNull: false,
      },
      introduce: {
        type: Sequelize.TEXT,
        allowNull: false,
      },
    }, {
      sequelize,
      timestamps: true,
      paranoid: true,
      underscored: false,
      modelName: "User",
      tableName: "users",
      charset: "utf8",
      collate: "utf8_general_ci",
    });
  }
  static associate(db) {
    db.User.hasMany(db.Post, { foreignKey: "UserId", sourceKey: "id" });
  }
}

models > user.js

 

  • 유저 한 명은 여러 개의 게시글을 작성할 수 있으므로 hasMany 메서드를 사용한다.
  • 게시글 모델의 foreignKey가 내 모델의 id를 참조하고 있다.

 

const Sequelize = require("sequelize");

module.exports = class Post extends Sequelize.Model {
  static init(sequelize) {
    return super.init({
      title: {
        type: Sequelize.STRING(50),
        allowNull: false,
      },
      content: {
        type: Sequelize.STRING(200),
        allowNull: false,
      },
    }, {
      sequelize,
      timestamps: true,
      paranoid: true,
      underscored: false,
      modelName: "Post",
      tableName: "posts",
      charset: "utf8",
      collate: "utf8_general_ci",
    });
  }
  static associate(db) {
    db.Post.belongsTo(db.User, { foreignKey: "UserId", targetKey: "id" });
  }
}

models > post.js

 

  • 유저 모델의 정보가 들어있으므로 belongsTo 메서드를 사용한다.
  • 게시글 모델은 유저 모델에 속해있다.
  • targetKey는 유저 모델의 id를 가리킨다.

 

const Sequelize = require("sequelize");

const User = require("./user");
const Post = require("./post");

const env = process.env.NODE_ENV || "development";
const config = require("../config/config.json")[env];
const db = {};

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

db.sequelize = sequelize;
db.User = User;
db.Post = Post;

User.init(sequelize);
Post.init(sequelize);

User.associate(db);
Post.associate(db);

module.exports = db;

models > index.js

 

  • 유저 모델과 게시글 모델을 불러온다.
  • 불러온 모델들을 db 객체에 담고 init 메서드를 사용하여 호출한다.
  • associate 메서드에 db 객체를 넣어 호출한다.

 

const router = require("express").Router();
const indexController = require("../controllers/indexController");

router.get("/", indexController.userPost);

module.exports = router;

routes > index.js

 

  • "/" 경로로 get 요청을 통해 유저가 작성한 게시글을 확인한다.

 

const models = require("../models");

exports.userPost = async (req, res) => {
  // 관계 메서드
  const user = await models.User.findOne({
    where: { id: 1 },
  });
  const userPost = await user.getPosts();
  
  // include
  const user2 = await models.User.findOne({
    where: { id: 1 },
    include: [{
      model: models.Post,
    }],
  });
};

controllers > indexController.js

 

관계 메서드
include

 

  • 모델 간의 관계가 설정되어 있다면 getPosts / addPost / setPost / removePost 관계 메서드를 사용할 수 있다.
  • include는 MySQL의 JOIN 기능이다.
  • 어떤 모델과 관계가 있는지 include에 넣어주면 된다.
  • 다른 모델과의 관계가 있을 수 있기에 배열로 넣어준다.
  • 관계 메서드나 include를 상황에 맞게 사용한다.

'데이터베이스' 카테고리의 다른 글

DBMS RDBMS Transaction  (0) 2022.05.08
Sequelize N:M associate  (0) 2022.05.05
Sequelize 1:1 associate  (0) 2022.05.05
Sequelize Model  (0) 2022.05.04
Sequelize ORM  (0) 2022.05.03