アソシエーション
直接的なサブクラス
Sequelizeにおけるアソシエーションの作成は、モデル(ソース)に対してbelongsTo / hasOne / hasMany / belongsToMany関数のいずれかを呼び出し、関数への最初の引数として別のモデル(ターゲット)を提供することによって行われます。
- hasOne - ターゲットに外部キーを追加し、ソースに単数形のアソシエーションミキシンを追加します。
- belongsTo - ソースに外部キーと単数形のアソシエーションミキシンを追加します。
- hasMany - ターゲットに外部キーを追加し、ソースに複数形のアソシエーションミキシンを追加します。
- belongsToMany - 結合テーブルを使用してN:Mアソシエーションを作成し、ソースに複数形のアソシエーションミキシンを追加します。結合テーブルはsourceIdとtargetIdで作成されます。
アソシエーションを作成すると、属性に外部キー制約が追加されます。n:mを除くすべてのアソシエーションは、更新時に`CASCADE`、削除時に`SET NULL`を使用します。n:mは削除時にも`CASCADE`を使用します。
アソシエーションを作成する際、`as`オプションを使用してエイリアスを指定できます。これは、同じモデルが2回関連付けられている場合、またはアソシエーションをターゲットモデルの名前以外の名前で呼び出したい場合に便利です。
例として、ユーザーが複数の画像を持ち、そのうち1つがプロフィール画像であるケースを考えてみましょう。すべての画像は`userId`を持ちますが、ユーザーモデルはユーザーのプロフィール画像を簡単にロードできるように`profilePictureId`も持っています。
User.hasMany(Picture)
User.belongsTo(Picture, { as: 'ProfilePicture', constraints: false })
user.getPictures() // gets you all pictures
user.getProfilePicture() // gets you only the profile picture
User.findAll({
where: ...,
include: [
{ model: Picture }, // load all pictures
{ model: Picture, as: 'ProfilePicture' }, // load the profile picture.
// Notice that the spelling must be the exact same as the one in the association
]
})
Sequelizeによって追加された外部キー列を完全に制御するには、`foreignKey`オプションを使用します。これは、名前を指定する文字列、または`sequelize.define`に渡されるものと同等のオブジェクト型の定義のいずれかになります。
User.hasMany(Picture, { foreignKey: 'uid' })
Pictureの外部キー列は、デフォルトの`userId`ではなく`uid`と呼ばれるようになります。
User.hasMany(Picture, {
foreignKey: {
name: 'uid',
allowNull: false
}
})
これは、`uid`列がnullにできないことを指定しています。ほとんどの場合、これはSequelizeが自動的に作成する外部キー制約によってすでにカバーされていますが、外部キーが無効になっている場合(例えば、循環参照のため(下記の`constraints: false`を参照))に役立つ場合があります。
関連付けられたモデルを取得する際、クエリを特定のモデルのロードのみに制限できます。これらのクエリは、`find` / `findAll`へのクエリと同じ方法で記述されます。JPGの画像のみを取得するには、次のようにします。
user.getPictures({
where: {
format: 'jpg'
}
})
アソシエーションの更新と新規追加にはいくつかの方法があります。ユーザーと画像の例を続けます。
user.addPicture(p) // Add a single picture
user.setPictures([p1, p2]) // Associate user with ONLY these two picture, all other associations will be deleted
user.addPictures([p1, p2]) // Associate user with these two pictures, but don't touch any current associations
関連付けられたモデルに単一主キーがある場合、アソシエーション関数に完全なオブジェクトを渡す必要はありません。
user.addPicture(req.query.pid) // Here pid is just an integer, representing the primary key of the picture
上記の例では、ユーザーが彼のプロフィール画像に属していることを指定しました。概念的には、これは意味がないかもしれませんが、ユーザーモデルに外部キーを追加したいので、これが方法です。
プロフィール画像に対して`constraints: false`を指定した点にも注意してください。これは、ユーザーから画像(profilePictureId)、画像からユーザー(userId)への外部キーを追加するためです。両方に外部キーを追加すると、循環依存関係が作成され、Sequelizeはユーザーが画像に依存し、画像がユーザーに依存するため、どのテーブルを最初に作成するかを知ることができません。このような問題は、モデルがデータベースに同期される前にSequelizeによって検出され、`Error: Cyclic dependency found. 'users' is dependent of itself`のようなエラーが表示されます。このようなエラーが発生した場合は、一部の制約を無効にするか、アソシエーションを完全に再考する必要があります。