4
4

More than 3 years have passed since last update.

nodejsのorマッパー sequelize のaccociaton

Last updated at Posted at 2020-03-01

associationのまとめ

belongsTo

1つの関連をもつ。

  • 例) Players.belongsTo(Teams)

Playersに外部キーteamIdが自動追加される。

hasOne

1つの関連をもつ。

  • 例) Players.hasOne(Profiles)

Profilesに外部キーplayerIdが自動追加される。include時、最初の1件のみ出力される。

hasMany

複数の関連をもつ。

  • 例) Players.hasMany(Profiles)

Profilesに外部キーplayerIdが自動追加される。include時、複数件出力される。

belongsToMany

多対多の中間テーブルを持つ。

  • 例1)Players.belongsToMany(Teams, { through: TeamPlayers })
    中間テーブル'TeamPlayers'が作成され、そこに外部キーteamId playerIdが自動追加される

  • 例2)Teams.belongsToMany(Players, { through: TeamPlayers })

    中間テーブル'TeamPlayers'が作成され、そこに外部キーplayerId teamIdが自動追加される

belongToとhasOneの違い

挙動はほぼ同じ。指定の順が変わっただけ。

belongsTo のサンプル

// model(テーブル)を定義
// 主キー`id`や`createdAt`、`updatedAt`は勝手に定義されるので記述不要
const Players = sequelize.define('players', {
    name: Sequelize.STRING,
});
const Teams = sequelize.define('teams', {
    name: Sequelize.STRING,
});
Players.belongsTo(Teams, { foreignKey: 'team_id' })   // playersに外部キー'team_id'が作成される。foreignKeyを省略した場合、キャメルケースでid名'teamId'が自動生成される

// modelを元にDBテーブルの作成({force:true}オプションは、テーブルdrop&create)
await Players.sync({ force: true });
await Teams.sync({ force: true });

// レコードのcreate
const team1 = await Teams.create({ name: 'team1' });
const player1 = await Players.create({ name: 'player1', team_id: team1.id });

// レコード取得
const player = await Players.findById(player1.id, { include: Teams })

console.log(player.get({ plain: true }))

出力結果

{ id: 1,
    name: 'player1',
    createdat: 2019-08-29t02:36:21.464z,
    updatedat: 2019-08-29t02:36:21.464z,
    team_id: 1,
    team:
    { id: 1,
    name: 'team1',
    createdat: 2019-08-29t02:36:21.448z,
    updatedat: 2019-08-29t02:36:21.448z } }

以下でも、teams : players = 1 : n で取得できそうだが、できない

const team = await Teams.findById(team1.id, { include: Players})

出力結果

  failed: sequelizeeagerloadingerror: players is not associated to teams!

hasOne のサンプル

// model(テーブル)を定義
const Players = sequelize.define('players', {
    name: Sequelize.STRING,
});
const Profiles= sequelize.define('profiles', {
    name: Sequelize.STRING,
});
Players.hasOne(Profiles,{foreignKey:'player_id'})

// modelを元にDBテーブルの作成
await Players.sync({ force: true });
await Profiles.sync({ force: true });

// レコードのcreate
const player1= await Players.create({ name: 'player1' });
const profile1= await Profiles.create({ name: 'profile1', player_id: player1.id });
const profile2= await Profiles.create({ name: 'profile2', player_id: player1.id });

// レコードの取得
const player = await Players.findById(player1.id, { include: Profiles})

console.log(player.get({ plain: true }))

出力結果

{ id: 1,
    name: 'player1',
    createdAt: 2019-08-29T03:59:30.432Z,
    updatedAt: 2019-08-29T03:59:30.432Z,
    profile:
    { id: 1,
    name: 'profile1',
    createdAt: 2019-08-29T03:59:30.448Z,
    updatedAt: 2019-08-29T03:59:30.448Z,
    player_id: 1 } }

hasMany のサンプル

// model(テーブル)を定義
const Players = sequelize.define('players', {
    name: Sequelize.STRING,
});
const Profiles= sequelize.define('profiles', {
    name: Sequelize.STRING,
});
Players.hasMany(Profiles,{foreignKey:'player_id'})

// modelを元にDBテーブルの作成
await Players.sync({ force: true });
await Profiles.sync({ force: true });

// レコードのcreate
const player1= await Players.create({ name: 'player1' });
const profile1= await Profiles.create({ name: 'profile1', player_id: player1.id });
const profile2= await Profiles.create({ name: 'profile2', player_id: player1.id });

// レコードの取得
const player = await Players.findById(player1.id, { include: Profiles})

// hasOneだと最初の1件しか取得できないがhasManyだと全て取得できる
console.log(player.get({ plain: true }))

出力結果

{ id: 1,
    name: 'player1',
    createdAt: 2019-08-29T04:13:05.396Z,
    updatedAt: 2019-08-29T04:13:05.396Z,
    profiles:
    [ { id: 1,
        name: 'profile1',
        createdAt: 2019-08-29T04:13:05.412Z,
        updatedAt: 2019-08-29T04:13:05.412Z,
        player_id: 1 },
    { id: 2,
        name: 'profile2',
        createdAt: 2019-08-29T04:13:05.428Z,
        updatedAt: 2019-08-29T04:13:05.428Z,
        player_id: 1 } ] }

belongsToMany のサンプル

// model(テーブル)を定義
// 主キー'id'や'createdAt'、'updatedAt'は勝手に定義されるので記述不要
const Players = sequelize.define('players', {
    name: Sequelize.STRING,
});
const Teams = sequelize.define('teams', {
    name: Sequelize.STRING,
});
const TeamPlayers = sequelize.define('team_players', {
    name: Sequelize.STRING,
});

// 中間テーブル'TeamPlayers'を作成し、そこに'team_id'を追加する
Players.belongsToMany(Teams, { through: TeamPlayers, foreignKey: 'team_id' }) 
// 中間テーブル'TeamPlayers'を作成し、そこに'team_id'を追加する
Teams.belongsToMany(Players, { through: TeamPlayers, foreignKey: 'player_id' })

await TeamPlayers.sync({ force: true });
await Players.sync({ force: true });
await Teams.sync({ force: true });

// レコードのcreate
const team1 = await Teams.create({ name: 'team1' });
const team2 = await Teams.create({ name: 'team2' });
const player1 = await Players.create({ name: 'player1' });
player1.addTeam(team1,{ status: 'started' })
player1.addTeam(team2,{ status: 'started' })
const player2 = await Players.create({ name: 'player2' });
player2.addTeam(team1,{ status: 'started' })
player2.addTeam(team2,{ status: 'started' })

// レコード取得
const player = await Players.findById(player1.id, { include: Teams })
console.log(player.get({ plain: true }))

const team= await Teams.findById(team1.id, { include: Players})
console.log(team.get({ plain: true }))

出力結果

{ id: 1,
  name: 'player1',
  createdAt: 2019-08-29T05:56:11.200Z,
  updatedAt: 2019-08-29T05:56:11.200Z,
  teams:
   [ { id: 1,
       name: 'team1',
       createdAt: 2019-08-29T05:56:11.168Z,
       updatedAt: 2019-08-29T05:56:11.168Z,
       team_players: [Object] },
     { id: 2,
       name: 'team2',
       createdAt: 2019-08-29T05:56:11.184Z,
       updatedAt: 2019-08-29T05:56:11.184Z,
       team_players: [Object] } ] }

{ id: 1,
  name: 'team1',
  createdAt: 2019-08-29T05:56:11.168Z,
  updatedAt: 2019-08-29T05:56:11.168Z,
  players:
   [ { id: 1,
       name: 'player1',
       createdAt: 2019-08-29T05:56:11.200Z,
       updatedAt: 2019-08-29T05:56:11.200Z,
       team_players: [Object] },
     { id: 2,
       name: 'player2',
       createdAt: 2019-08-29T05:56:11.217Z,
       updatedAt: 2019-08-29T05:56:11.217Z,
       team_players: [Object] } ] }
4
4
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
4
4