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モデルが必要な場合。