Saltar al contenido

Cómo implementar una asociación de muchos a muchos en Sequelize

Nuestros mejores desarrolladores han agotado sus provisiones de café, en su búsqueda a tiempo completo por la respuesta, hasta que Fernando halló la contestación en Gitea así que hoy la comparte con nosotros.

Solución:

Sequelize Association Cheatsheet

Actualizado para Sequelize v2/3/4/5

En general, creo que los problemas son que estamos confundidos acerca de qué tablas se crearon y qué métodos se obtienen mediante asociaciones.

Nota: La definición de ForeignKey o el nombre de la tabla cruzada es opcional. Sequelize lo crea automáticamente, pero definirlo permite a los codificadores leer los modelos y descubrir qué es lo extraño. keys/los nombres de las tablas cruzadas son, en lugar de adivinar o necesitar acceder a la base de datos.

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')

NUEVO MÉJICO

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'
    
)

¿Por qué el detallado “Parent_parentId” y no solo “parentId”? Esto es para que sea obvio que es un extranjero. key que pertenecía a “Padre”. En la mayoría de los casos, está bien usar el “parentId” más sucinto.*

Las asociaciones le brindan 2 funcionalidades: (1) carga ansiosa y (2) métodos DAO:

1. Incluir (carga ansiosa)

DB.Parent.findOne( 
    where:  id: 1 ,
    include: [ DB.Child ]
).then(parent => 

    // you should get `parent.Child` as an array of children. 

)

2. Métodos ganados por hasOne(), hasMany() y proudTo()/belongsToMany()

Las asociaciones dan los métodos del objeto de acceso a datos (DAO):

Tiene uno():

Al establecer un Parent.hasOne(Child)métodos disponibles para parent instancia DAO:

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

)

tiene muchas():

Al establecer un Parent.hasMany(Child)métodos disponibles para parent instancia DAO:

parent.getChildren,
parent.setChildren,
parent.addChild,
parent.addChildren,
parent.createChild,
parent.removeChild,
parent.hasChild,
parent.hasChildren,

pertenece a()/perteneceamuchos:

Al establecer un Child.belongsTo(Parent)métodos disponibles para child instancia DAO:

child.getParent,
child.setParent,
child.createParent,

//belongsToMany
child.getParents,
child.setParents,
child.createParents,

También puedes tener varias relaciones.

Padres Naturales/Hijos

// 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'
)

Padres adoptivos/niños

Parent.belongsToMany(Child, 
    as: 'Foster',
    through: 'Parent_Child',
    foreignKey: 'Parent_parentId'
)

Child.belongsToMany(Parent, 
    as: 'Foster',
    through: 'Parent_Child',
    foreignKey: 'Child_childId'
);

Lo anterior creará el Parent_Child mesa cruzada, con NaturalId y FosterId.

elimine el modelo BookArticles y actualice la relación con:

m.Book.hasMany(m.Article, through: 'book_articles');
m.Article.hasMany(m.Books, through: 'book_articles');

Así es como resolví el problema similar. Tenía dos modelos, un modelo de usuario.

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

y un modelo a seguir

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

Luego creé el modelo de unión UserRole

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

Nota: debe definir explícitamente la identificación para UserRole; de ​​lo contrario, la secuenciación utilizará los dos foráneos keys en este caso user_id y role_id como tu principal keys.

Luego creé la relación pertenece a muchos de la siguiente manera

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' );

Reseñas y calificaciones

Si haces scroll puedes encontrar las explicaciones de otros usuarios, tú también tienes el poder dejar el tuyo si te apetece.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *