SQL複合主キーをSequelizeインデックスに変換する

PRIMARY KEY (col1, col2)で定義されたSQL複合主キーがSequelizeモデルでindexes設定オプションを使用してどのように表現されるかを解説します。

Advanced Features

詳細な説明

Sequelizeでの複合主キー

SQLテーブルが複数カラムにまたがる主キーを定義している場合、コンバーターは個別のフィールドにprimaryKey: trueを使用するのではなく、indexes配列で複合キーを表現するSequelizeモデルを生成します。

SQL定義

CREATE TABLE inventory (
  warehouse_id INTEGER NOT NULL,
  product_id INTEGER NOT NULL,
  quantity INTEGER NOT NULL DEFAULT 0,
  last_checked TIMESTAMP,
  PRIMARY KEY (warehouse_id, product_id)
);

生成されるSequelizeモデル

Inventory.init({
  warehouse_id: { type: DataTypes.INTEGER, allowNull: false },
  product_id: { type: DataTypes.INTEGER, allowNull: false },
  quantity: { type: DataTypes.INTEGER, allowNull: false, defaultValue: 0 },
  last_checked: { type: DataTypes.DATE, allowNull: true },
}, {
  sequelize,
  modelName: 'Inventory',
  tableName: 'inventory',
  indexes: [
    { fields: ['warehouse_id', 'product_id'], unique: true, name: 'PRIMARY' },
  ],
});

単一主キーとの違い

単一主キーの場合、SequelizeはフィールドにprimaryKey: trueを使用します。複合キーの場合、SequelizeのprimaryKeyオプションは一度に1つのフィールドしかサポートしないため、indexesアプローチが必要です。ユニークインデックスが実質的に複合主キー制約を適用します。

複合キーでのクエリ

複合キーを持つモデルをクエリする場合、where句付きのfindOneを使用します:

const item = await Inventory.findOne({
  where: { warehouse_id: 1, product_id: 42 }
});

findByPk()は単一値を期待するため、複合キーでは機能しないことに注意してください。

マイグレーションの考慮事項

マイグレーション(モデルではなく)を生成する場合、Sequelizeは複合主キーにqueryInterface.addConstraintを使用します。モデル定義だけでは制約は作成されません。sync()または複合キーを明示的に定義するマイグレーションが必要です。

ジャンクションテーブル

複合主キーはジャンクションテーブル(多対多)で最も一般的です。両方のカラムが他のテーブルを参照している場合、そのモデルはbelongsToManyアソシエーションのthroughテーブルである可能性が高いです。

ユースケース

倉庫と商品の組み合わせごとに在庫レベルを追跡する在庫管理システムを構築しており、複合主キーが各組み合わせの一意性を保証し、効率的な検索を可能にする場合。

試してみる — SQL to Sequelize Model

フルツールを開く