데이터베이스

Sequelize 1:1 associate

realtrynna 2022. 5. 5. 15:25

Sequelize 1:1 associate

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

 

폴더 구조

 

1:1

유저 모델의 정보를 담고 있는 세부 정보 모델 간의 일대일 관계

- 사용자 모델과 사용자의 세부 정보를 담고 있는 모델 간의 관계는 1:1이다.

- 사용자 한 명은 자신의 정보를 담고 있는 테이블과만 관계가 있다.

- 세부 정보 테이블도 한 사람만을 가리킨다.

- 유저 모델 hasOne/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.hasOne(db.UserInfo, { foreignKey: "UserId", sourceKey: "id" });
  }
}

models > user.js

 

  • 유저 모델이 유저의 세부 정보를 포함하므로 hasOne 메서드를 사용한다.
  • 세부 정보 모델의 foreignKey가 내 모델의 id를 참조하고 있다.

 

const Sequelize = require("sequelize");

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

models > userInfo.js

 

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

 

const Sequelize = require("sequelize");

const User = require("./user");
const UserInfo = require("./userInfo");

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.UserInfo = UserInfo;

User.init(sequelize);
UserInfo.init(sequelize);

User.associate(db);
UserInfo.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.indexRender);

module.exports = router;

 

  • "/" 경로로 get 요청을 통해 유저와 세부 정보 테이블의 데이터를 확인한다.

 

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

exports.indexRender = async (req, res) => {
  // 관계 메서드
  const getUser = await models.User.findOne({
    where: {
      id: 1,
    },
  });
  const result = await user.getUserInfo();

  // include
  const getUser2 = await models.User.findOne({
    where: {
      id: 1,
    },
    include: [{
      model: models.UserInfo,
    }],
  });
};

controllers > indexController.js

 

관계 메서드
include

 

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

 

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

Sequelize N:M associate  (0) 2022.05.05
Sequelize 1:N associate  (0) 2022.05.05
Sequelize Model  (0) 2022.05.04
Sequelize ORM  (0) 2022.05.03
MongoDB Mongoose  (0) 2022.01.24