Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
23
Help us understand the problem. What is going on with this article?
@NewGyu

Sequelizeのassociation

More than 5 years have passed since last update.

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

となります。

23
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
NewGyu

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
23
Help us understand the problem. What is going on with this article?