SQL外部キーリレーションシップからSequelize hasManyを生成する

コンバーターがSQL FOREIGN KEY制約からhasManyの逆アソシエーションをどのように推論し、リレーションシップの両側のコメント付きヒントを生成するかを解説します。

Associations

詳細な説明

hasMany: belongsToの逆側

すべてのbelongsToリレーションシップには、対応するhasMany(またはhasOne)が反対側にあります。コンバーターがテーブルBからテーブルAへの外部キーを検出すると、両方を生成します:

  1. B.belongsTo(A) — 子モデル上
  2. A.hasMany(B) — 逆アソシエーションセクションのコメントヒントとして

例:UsersとPosts

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

CREATE TABLE posts (
  id SERIAL PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  author_id INTEGER NOT NULL REFERENCES users(id)
);

コンバーターは以下を生成します:

// Postモデル上:
// Post.belongsTo(User, { foreignKey: 'author_id', targetKey: 'id' });

// 逆アソシエーションセクション:
// User.hasMany(Post, { foreignKey: 'author_id' });

実行可能コードではなくコメントの理由

コンバーターがhasManyをコメントとして生成する理由:

  1. 循環依存: モジュラープロジェクトでは、モデルファイルが互いにインポートします。両方のアソシエーション側をモデルファイルに配置すると循環インポートが発生します。
  2. アソシエーション設定パターン: ベストプラクティスは、すべてのモデルがロードされた後に中央のmodels/index.jsまたは専用のassociations.jsファイルでアソシエーションを呼び出すことです。
  3. 柔軟性: hasManyの代わりにhasOneが必要な場合や、asエイリアス、onDeleteonUpdateオプションを追加したい場合があります。

両側の設定

// models/associations.js
const { User, Post, Comment } = require('./');

User.hasMany(Post, { foreignKey: 'author_id', as: 'posts' });
Post.belongsTo(User, { foreignKey: 'author_id', as: 'author' });

Post.hasMany(Comment, { foreignKey: 'post_id', as: 'comments' });
Comment.belongsTo(Post, { foreignKey: 'post_id' });

イーガーローディング

両側が設定されると、Sequelizeのincludeオプションでイーガーローディングが使用できます:

const user = await User.findByPk(1, {
  include: [{ model: Post, as: 'posts' }]
});

ユースケース

複数の1対多リレーションシップを持つマルチテーブルスキーマがあり、コンバーターがすべての外部キーを識別してhasManyヒントを提供するため、Sequelizeアソシエーションファイルですべてのリレーションシップの両側を素早く設定できる場合。

試してみる — SQL to Sequelize Model

フルツールを開く