Sequelize Relationships: `hasOne` vs `belongsTo` ================================================ Docs ---- - [Docs Source](http://docs.sequelizejs.com/en/latest/docs/associations/) - [belongsTo API](http://docs.sequelizejs.com/en/latest/api/associations/belongs-to/) - [hasOne API](http://docs.sequelizejs.com/en/latest/api/associations/has-one/) 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** ```js 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** ```js 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** ```js 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** ```js 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** ```js 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!