How to implement many to many association in sequelize

前端 未结 4 651
庸人自扰
庸人自扰 2020-11-27 09:33

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

models/books.js

module.exports =          


        
相关标签:
4条回答
  • 2020-11-27 09:51

    delete BookArticles model and update relation to:

    m.Book.hasMany(m.Article, {through: 'book_articles'});
    m.Article.hasMany(m.Books, {through: 'book_articles'});
    
    0 讨论(0)
  • 2020-11-27 10:00

    M:M relation through table BookArticles:

    m.Book.belongsToMany(m.Article, {through: m.BookArticles});
    m.Article.belongsToMany(m.Books, {through: m.BookArticles});
    
    0 讨论(0)
  • 2020-11-27 10:03

    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.

    0 讨论(0)
  • 2020-11-27 10:07

    This is how i solved the similar problem i had two models a user model

    var user = sequelize.define('user', {
        name: {
            Sequelize.STRING(255)
        },
        email: {
            type: Sequelize.STRING(255),
            unique: true,
            validate: {
                isEmail: true
            }
        }
    });
    

    and a roles model

    var Role = sequelize.define('role', {
        name: {
            Sequelize.ENUM('ER', 'ALL', 'DL')
        },
        description: {
            type: Sequelize.TEXT
        }
    });
    

    Then i created the union model UserRole

    var UserRole = sequelize.define('user_role', {
        id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true
        },
        name: {
            type: Sequelize.ENUM('Admin', 'Staff', 'Customer', 'Owner')
        }
    });
    

    Note: you have to explicitly define the id for UserRole otherwise sequelize will use the two foreign keys in this case user_id and role_id as your primary keys.

    Then i created the belongs to many relationship as follows

    User.belongsToMany(Role, { as: 'Roles', through: { model: UserRole, unique: false }, foreignKey: 'user_id' });
    Role.belongsToMany(User, { as: 'Users', through: { model: UserRole, unique: false }, foreignKey: 'role_id' });
    
    0 讨论(0)
提交回复
热议问题