Skip to content

Instantly share code, notes, and snippets.

@bicho19
Forked from AloofBuddha/associations.md
Created May 28, 2022 14:56
Show Gist options
  • Save bicho19/ee1215f4f5f51149c87c8dfc78dcd717 to your computer and use it in GitHub Desktop.
Save bicho19/ee1215f4f5f51149c87c8dfc78dcd717 to your computer and use it in GitHub Desktop.
Sequelize Relationships: hasOne vs belongsTo

Sequelize Relationships: hasOne vs belongsTo

Docs

Intro

First, what's the same - they both define a One-to-One relationship: an association between exactly two models connected by a single foreign key. The difference between them is in which model is the source and which is the target, and what additional helper functions are provided when the relationship is defined.

They are conversely related:

  • modelA.belongsTo(modelB) - modelA is the source, modelB is the target
  • modelB.hasOne(modelA) - modelB is the source, modelA is the target

Here's some examples:

Defining Models

This is common to both

Sequelize

var Artist = this.sequelize.define('artist', { name: Sequelize.STRING })
var Band   = this.sequelize.define('band', { name: Sequelize.STRING });

PostgreSQL

artists
=======
id  |      name     
---------------------
1   |  "Big Boi"
2   |  "Andre 3000"
3   |  "Jack White"
4   |  "Meg White" 


bands
=====
id  |             name          
---------------------------------
1   |    "Outkast"
2   |    "The White Stripes"

belongsTo

Artist.belongsTo(Band) will create a one-to-one association with Artist as the source and Band as the target. This means the foreign key for Band will be added to the Artist model.

Note how many artists can belong to the same band!

Sequelize

var Artist = this.sequelize.define('artist', { name: Sequelize.STRING })
var Band   = this.sequelize.define('band', { name: Sequelize.STRING });

Artist.belongsTo(Band); 
// adds 'bandId' field to Artist model
// adds Artist instance methods 'getBand', 'setBand', and 'createBand'

PostgreSQL

artists
=======
id  |      name         |  bandId
---------------------------------
1   |  "Big Boi"        | 1
2   |  "Andre 3000"     | 1
3   |  "Jack White"     | 1
4   |  "Meg White"      | 2


bands
=====
id  |             name          
---------------------------------
1   |    "Outkast"
2   |    "The White Stripes"

Example

Artist.findById(1)
  .then(function (artist) {
    console.log(artist.name);    // "Big Boi"
    console.log(artist.bandId); // 1
    
    return artist.getBand();    // like all database queries, returns a Promise
  })
  .then(function (band) {
    console.log(band);         // "Outkast" 
  });

hasOne

Band.hasOne(Artist) will create a one-to-one association with Band as the source and Artist as the target. This means the foreign key for Artist will be added to the Band model (inverse of belongsTo).

Note how a band can only have one lead!

Sequelize

var Artist = this.sequelize.define('artist', { name: Sequelize.STRING })
var Band   = this.sequelize.define('band', { name: Sequelize.STRING });

Band.hasOne(Artist, { as: "lead" }); 
// adds 'leadId' field to Band model
// adds Band instance methods 'getLead', 'setLead', and 'createLead'

PostgreSQL

artists
=======
id  |      name         
--------------------
1   |  "Big Boi"        
2   |  "Andre 3000"     
3   |  "Jack White"     
4   |  "Meg White"      


bands
=====
id  |             name         |  leadId
-------------------------------------------
1   |    "Outkast"             | 2
2   |    "The White Stripes"   | 3

Example

Band.findById(1)
  .then(function (band) {
    console.log(band.name);    // "Outkast"
    console.log(band.leadId); // 2
    
    return band.getLead();    // like all database queries, returns a Promise
  })
  .then(function (artist) {
    console.log(artist);         // "Andre 3000" 
  });

Note: this is not meant to be a statement on who the 'lead' of Outkast is: Andre 3000 and Big Boi are both talented in their own right!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment