44
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Sequelizeのassociation

Posted at

http://docs.sequelizejs.com/en/latest/docs/associations/
ここに書いてあるのですが若干理解に詰まったのでメモ書きを残します。

Sequlizeに限らずActiveRecordとかもだいたい同じ考え方だと想います。

belongsTo

直訳すると「属している」です。

モデル定義1
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

「属している」という言葉にこだわるとわかりにくい例です。

モデル定義2
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
モデル定義3
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
  • otherKeyもthroughにある
    • 指しているものはTargetのprimaryKey

となります。

44
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?