Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement many to many association in sequelize

I have two tables: Books and Articles with a many-to-many relationship between them. Joining table is BookArticles.

models/books.js

module.exports = function(sequelize, DataTypes) {   return Food = sequelize.define("Book", {     id: {       type: DataTypes.INTEGER,       primaryKey: true,       allowNull: false,       autoIncrement: true,       unique: true     }   }); } 

models/articles.js

module.exports = function(sequelize, DataTypes) {   return Food = sequelize.define("Article", {     id: {       type: DataTypes.INTEGER,       primaryKey: true,       allowNull: false,       autoIncrement: true,       unique: true     }   }); } 

models/bookArticles.js

module.exports = function(sequelize, DataTypes) {   return Food = sequelize.define("BookArticles", {     id: {       type: DataTypes.INTEGER,       primaryKey: true,       allowNull: false,       autoIncrement: true,       unique: true     },    bookId: {       type: DataTypes.INTEGER,       references: 'Book',       referencesKey: 'id',       allowNull: false     },     ArticleId: {       type: DataTypes.INTEGER,       references: 'Article',       referencesKey: 'id',       allowNull: false     },   }); } 

And models/index.js

m.BookArticles.belongsTo(m.Book); m.Book.hasMany(m.Article, {through: m.BookArticles});   m.BookArticles.belongsTo(m.Article); m.Article.hasMany(m.Books, {through: m.BookArticles}); 

but I could not get book articles

How can I get it ??

like image 458
Anuj Avatar asked Apr 09 '14 09:04

Anuj


People also ask

How do I use association in Sequelize?

Creating associations in sequelize is done by calling one of the belongsTo / hasOne / hasMany / belongsToMany functions on a model (the source), and providing another model as the first argument to the function (the target). hasOne - adds a foreign key to the target and singular association mixins to the source.

Are there many relations in Sequelize?

The A.hasMany(B) association means that a One-To-Many relationship exists between A and B , with the foreign key being defined in the target model ( B ). These three calls will cause Sequelize to automatically add foreign keys to the appropriate models (unless they are already present).


1 Answers

Sequelize Association Cheatsheet

Updated for Sequelize v2/3/4/5

Generally I think the problems are that we are confused about what tables created, and what methods are gained by associations.

Note: Defining foreignKey or cross table name are optional. Sequelize automatically creates it, but defining it allows coders to read the models and find out what the foreign keys/cross table names are, instead of guessing or needing to access the database.

TLDR;

O:O

// foreign key has to be defined on both sides. Parent.hasOne(Child, {foreignKey: 'Parent_parentId'}) // "Parent_parentId" column will exist in the "belongsTo" table. Child.belongsTo(Parent, {foreignKey: 'Parent_parentId'}) 

O:M

Parent.hasMany(Child, {foreignKey: 'Parent_parentId'}) Child.belongsTo(Parent, {foreignKey: 'Parent_parentId'}) 

N:M

Parent.belongsToMany(     Child,      {         // this can be string (model name) or a Sequelize Model Object Class         // through is compulsory since v2         through: 'Parent_Child',          // GOTCHA         // note that this is the Parent's Id, not Child.          foreignKey: 'Parent_parentId'     } )  /* The above reads: "Parents" belongs to many "Children", and is recorded in the "Parent_child" table, using "Parents"'s ID. */  Child.belongsToMany(     Parent,      {         through: 'Parent_Child',          // GOTCHA         // note that this is the Child's Id, not Parent.         foreignKey: 'Child_childId'     } ) 

Why the verbose "Parent_parentId" and not just "parentId"? This is to make it obvious that it's a foreign key that belonged to "Parent". In most cases it's okay to just use the more succinct "parentId".*

Associations gives you 2 functionality: (1) Eager loading and (2) DAO Methods:

1. Include (Eager loading)

DB.Parent.findOne({      where: { id: 1 },     include: [ DB.Child ] }).then(parent => {      // you should get `parent.Child` as an array of children.   }) 

2. Methods gained by hasOne(), hasMany() and belongsTo()/belongsToMany()

Associations give the Data Access Object (DAO) methods:

hasOne():

In setting a Parent.hasOne(Child), methods available to parent DAO instance:

DB.Parent.findOne({ where: { id: 1 } }).then(parent => {      // `parent` is the DAO     // you can use any of the methods below:     parent.getChild     parent.setChild     parent.addChild     parent.createChild     parent.removeChild     parent.hasChild  }) 
hasMany():

In setting a Parent.hasMany(Child), methods available to parent DAO instance:

parent.getChildren, parent.setChildren, parent.addChild, parent.addChildren, parent.createChild, parent.removeChild, parent.hasChild, parent.hasChildren, 
belongsTo()/belongsToMany:

In setting a Child.belongsTo(Parent), methods available to child DAO instance:

child.getParent, child.setParent, child.createParent,  //belongsToMany child.getParents, child.setParents, child.createParents, 

You can also have multiple relationships

Natural Parents/Children
// a parent can have many children Parent.belongsToMany(Child, {     as: 'Natural',     through: 'Parent_Child',     foreignKey: 'Parent_parentId' }) // a child must at least have 2 parents (natural mother and father) Child.belongsToMany(Parent, {     as: 'Natural',     through: 'Parent_Child',     foreignKey: 'Child_childId' }) 
Foster Parents/Children
Parent.belongsToMany(Child, {     as: 'Foster',     through: 'Parent_Child',     foreignKey: 'Parent_parentId' })  Child.belongsToMany(Parent, {     as: 'Foster',     through: 'Parent_Child',     foreignKey: 'Child_childId' }); 

The above will create the Parent_Child cross table, with NaturalId and FosterId.

like image 96
Calvintwr Avatar answered Oct 02 '22 14:10

Calvintwr