SQLジャンクションテーブルをSequelize belongsToManyに変換する

複合主キーを持つSQLジャンクションテーブルがSequelizeのbelongsToManyアソシエーションにthroughオプションとジョインテーブルモデルを使用してどのように変換されるかを学びます。

Advanced Features

詳細な説明

Sequelizeでの多対多リレーションシップ

SQLでの多対多リレーションシップは、両方の関連テーブルへの外部キーを持つジャンクションテーブル(ジョインテーブルまたはピボットテーブルとも呼ばれる)を使用し、多くの場合複合主キーを持ちます。コンバーターはこのパターンを検出し、適切なモデルを生成します。

SQLジャンクションテーブルパターン

CREATE TABLE students (
  id SERIAL PRIMARY KEY,
  name VARCHAR(255) NOT NULL
);

CREATE TABLE courses (
  id SERIAL PRIMARY KEY,
  title VARCHAR(255) NOT NULL
);

CREATE TABLE student_courses (
  student_id INTEGER NOT NULL REFERENCES students(id),
  course_id INTEGER NOT NULL REFERENCES courses(id),
  enrolled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (student_id, course_id)
);

生成されるモデル

コンバーターは両方の外部キーを持つジャンクションテーブルのモデルを生成します:

StudentCourse.init({
  student_id: {
    type: DataTypes.INTEGER, allowNull: false,
    references: { model: 'students', key: 'id' },
  },
  course_id: {
    type: DataTypes.INTEGER, allowNull: false,
    references: { model: 'courses', key: 'id' },
  },
  enrolled_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },
}, {
  sequelize,
  indexes: [{ fields: ['student_id', 'course_id'], unique: true, name: 'PRIMARY' }],
});

belongsToManyの設定

モデルが生成されたら、多対多アソシエーションを接続します:

Student.belongsToMany(Course, {
  through: StudentCourse,
  foreignKey: 'student_id',
  otherKey: 'course_id',
});

Course.belongsToMany(Student, {
  through: StudentCourse,
  foreignKey: 'course_id',
  otherKey: 'student_id',
});

ジャンクションテーブルの追加カラム

単純な多対多リレーションシップとは異なり、ジャンクションテーブルには追加カラム(上記のenrolled_atなど)がよくあります。Sequelizeのthroughモデルはこれらを保持し、結合結果のinstance.StudentCourse.enrolled_atでアクセスできます。

複合主キー

複合主キーPRIMARY KEY (student_id, course_id)はSequelizeモデルのindexes配列でユニークインデックスエントリに変換され、データベースレベルで組み合わせの一意性が保証されます。

ユースケース

学生が複数のコースに登録する学校登録システムをモデリングしており、ジャンクションテーブルに登録日が含まれるため、単純な文字列参照ではなくthroughテーブル用の完全なSequelizeモデルが必要な場合。

試してみる — SQL to Sequelize Model

フルツールを開く