http://docs.sequelizejs.com/en/latest/docs/associations/
ここに書いてあるのですが若干理解に詰まったのでメモ書きを残します。
Sequlizeに限らずActiveRecordとかもだいたい同じ考え方だと想います。
belongsTo
直訳すると「属している」です。
var Member = sequelize.define("Member",{
member_id : {... , primaryKey: true},
project_id: {...} //...k1
name : {...}
});
var Project = sequelize.define("Project",{
project_id : {... , primaryKey: true}, //...k2
name : {...}
});
Member.belongsTo(Project)
これはわかりやすいですね。Member.project_id
を外部キーとしてProject
とJOINします。
結合キーの指定
結合キーは明示的に指定するならこうです。
Member.belongsTo(Project,{
foreignKey: "project_id", //k1を指定
targetKey: "project_id" //k2を指定
});
省略してもモデル名とプライマリキー名から自動的に決めてくれるのですが、よくわからなくなるので明示的に書くことをオススメします。
ちなみにここで言うforeignKey
はRDBMSでいうConstraintとかIndexではなく、Columnのことを指します。
ちょっとわかりにくいbelongsTo
「属している」という言葉にこだわるとわかりにくい例です。
var Member = sequelize.define("Member",{
member_id : {... , primaryKey: true}, //...k4
project_id: {...} //...k1
name : {...}
});
var Project = sequelize.define("Project",{
project_id : {... , primaryKey: true}, //...k2
leader_id : {...} //...k3 プロジェクトリーダーのmember_id
name : {...}
});
-
belongsTo
...属している -
hasOne
...1つ持っている
この言葉尻だけを捉えると、Project.hasOne(Member, {as: "Leader"})
っぽいのですが
Project.belongsTo(Member,{
as: "Leader",
foreignKey: "leader_id", //k3を指定
targetKey: "member_id" //k4を指定
});
こちらです。
Source.belongsTo(Target)
は端的に言うと**foreignKey
がSource側にある**ということになります。
hasOne
対してSource.hasOne(Target)
は**foreignKey
がTarget側にある**ということになります。
先のモデル定義2の例だと、
Member.hasOne(Project,{
as: "LeadingProject",
foreignKey: "leader_id" //k1
})
となります。
hasOneの場合はtargetKey
の明示指定オプションは無いようです。SourceのprimaryKeyになるのは自明ということでしょうか。
hasMany
hasOneが理解できればhasManyも同じようなものです。foreignKey
がTarget側にあるということは相変わらずです。
Project.hasMany(Member,{
foreignKey: "project_id" //k1
})
belongsToMany
先までの例のモデル定義1,2ではメンバーは複数のプロジェクトを兼任できないデータ構造です。
現実的には複数プロジェクトを兼任することがありますね。
RDBでn対m関係を表現するには間に関連テーブルを入れるのが常套手段ですね。
- Project:ProjectMember = 1:n
- Member:ProjectMember = 1:m
var Member = sequelize.define("Member",{
member_id : {... , primaryKey: true}, //...kkk1
name : {...}
});
var Project = sequelize.define("Project",{
project_id : {... , primaryKey: true}, //...kkk2
name : {...}
});
var ProjectMember = sequelize.define("ProjectMember",{
project_id: {....}, //...kkk3
member_id: {...}, //...kkk4
});
Member.belongsToMany(Project,{
through: ProjectMember,
foreignKey: "member_id", //kkk4を指定
otherKey: "project_id" //kkk3を指定
})
このSource.belongsToMany(Target)
は
-
foreignKey
はthroughにある- 指しているものはSourceの
primaryKey
- 指しているものはSourceの
-
otherKey
もthroughにある- 指しているものはTargetの
primaryKey
- 指しているものはTargetの
となります。