J'ai deux tableaux: des livres et des articles avec une relation plusieurs-à-plusieurs entre eux. La table de jonction est 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
},
});
}
Et 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});
mais je n'ai pas pu obtenir d'articles de livre
Comment puis-je l'avoir ??
Update 17 Feb 15
: 1. La nouvelle v2 utilise 2x .belongsToMany()
pour N: M.
La compréhension de toutes ces associations a posé de nombreux problèmes.
En général, je pense que nous sommes confus quant à ce que sont les tables créées et quelles méthodes sont gagnées par les associations.
Le texte ci-dessous est quelque chose que j'ai écrit pour normaliser la façon dont je veux que mon équipe gère tout cela. Quant aux conventions de dénomination, vous pouvez l'ignorer si vous laissez simplement Sequelize tout par défaut.
Cependant, il est recommandé de nommer explicitement vos conventions pour de nombreuses raisons.
O: O, configurez une Parent.hasOne(Child)
ET Child.belongsTo(Parent)
.
O: M, configurez Parent.hasMany(Child)
ET Child.belongsTo(Parent)
.
N: M *, configurez Parent.belongsToMany(Child, {through: 'Parent_Child', foreignKey: 'Parent_rowId'})
et Child.belongsToMany(Parent, {through: 'Parent_Child', foreignKey: 'Child_rowId'})
.
Pour comprendre pourquoi nous faisons les associations ci-dessus, nous commençons par savoir quelles sont les méthodes que nous gagnons pour chaque modèle.
Lors de la définition d'une Parent.hasOne(Child)
, méthodes disponibles pour parent
instance DAO:
parent.getChild,
parent.setChild,
parent.addChild,
parent.createChild,
parent.removeChild,
parent.hasChild
Lors de la définition d'une Parent.hasMany(Child)
, méthodes disponibles pour parent
instance DAO:
parent.getChildren,
parent.setChildren,
parent.addChild,
parent.createChild,
parent.removeChild,
parent.hasChild,
parent.hasChildren
Lors de la définition d'une Child.belongsTo(Parent)
, méthodes disponibles pour child
instance DAO:
child.getParent,
child.setParent,
child.createParent
//belongsToMany
child.getParents,
child.setParents,
child.createParents
Parent.hasOne(Child, {foreignKey: 'Parent_childID'});
Child.belongsTo(Parent, {foreignKey: 'Parent_childID'});
Notez que nous avons explicitement défini nos ForeignKeys comme Parent_childID. C'est parce que nous voulons cette convention PascalCase_camelCase pour TableName_keyName.
Pour une relation N: M, procédez comme suit:
Parent.belongsToMany( Child, {
as: [Relationship],
through: [Parent_Child] //this can be string or a model,
foreignKey: 'Parent_rowId'
});
Child.belongsToMany(Parent, {
as: [Relationship2],
through: [Parent_Child],
foreignKey: 'Child_rowId'
});
*New in v2
: L'utilisation de "à travers" est désormais indispensable. En standard, en utilisant le paramètre "through", nous définissons explicitement tous les noms de tableau croisé pour la cohérence et moins de pièges.
Ce qui précède créera Parent_Child, avec RelationshipId et Relationship2ID.
Sequelize peut créer des clés étrangères automatiquement, mais je définis généralement les miennes.
TableNames: PascalCase
touches: camelCase
foreignkeys: TableNameInPascalCase_foreignKeyInCamelCase
Exemple: User_pictureId Signification: Cette clé de pictureId provient de la table User.
supprimer le modèle BookArticles et mettre à jour la relation avec:
m.Book.hasMany(m.Article, {through: 'book_articles'});
m.Article.hasMany(m.Books, {through: 'book_articles'});
Voilà comment j'ai résolu le problème similaire j'avais deux modèles un modèle utilisateur
var user = sequelize.define('user', {
name: {
Sequelize.STRING(255)
},
email: {
type: Sequelize.STRING(255),
unique: true,
validate: {
isEmail: true
}
}
});
et un modèle de rôles
var Role = sequelize.define('role', {
name: {
Sequelize.ENUM('ER', 'ALL', 'DL')
},
description: {
type: Sequelize.TEXT
}
});
J'ai ensuite créé le modèle d'union UserRole
var UserRole = sequelize.define('user_role', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.ENUM('Admin', 'Staff', 'Customer', 'Owner')
}
});
Remarque: vous devez définir explicitement l'ID pour UserRole sinon sequelize utilisera les deux clés étrangères dans ce cas user_id
et role_id
comme clés primaires.
Ensuite, j'ai créé la relation appartient à plusieurs comme suit
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' });
M:M
relation à travers la table BookArticles
:
m.Book.belongsToMany(m.Article, {through: m.BookArticles});
m.Article.belongsToMany(m.Books, {through: m.BookArticles});