Mysql
 sql >> Base de données >  >> RDS >> Mysql

Exemple simple de relation plusieurs-à-plusieurs utilisant Sequelize

Migrations

Je vous suggère d'utiliser sequelize migrations au lieu de faire sync() sur chaque modèle. Il y a un module - sequelize.cli qui vous permet de gérer facilement les migrations et les graines. Cela, d'une certaine manière, force une structure de projet en créant un fichier d'initialisation index.js à l'intérieur de /models répertoire du projet. Il suppose que toutes vos définitions de modèle seront dans ce répertoire. Ce script parcourt tous les fichiers de modèle (chaque définition de modèle est dans un fichier séparé, par exemple mentee.js , question.js ) et exécute sequelize.import() afin d'affecter ces modèles à l'instance sequelize - cela vous permet d'y accéder ultérieurement via sequelize[modelName] par exemple. sequelize.question .

Remarque : lors de la création de fichiers de migration, rappelez-vous des champs d'horodatage - createdAt , updatedAt et, éventuellement, deletedAt .

Synchroniser

Personnellement j'utilise sync() uniquement lorsque j'exécute les tests - cela peut être affiché en trois étapes

  1. effectuer sequelize.sync({ force: true }) afin de synchroniser tous les modèles
  2. exécuter des seeds de base de données (peut également être fait via sequelize-cli ),
  3. exécuter des tests.

Ceci est très confortable car vous permet de nettoyer la base de données avant d'exécuter des tests et, afin de distinguer le développement des tests, les tests peuvent utiliser différentes bases de données, par ex. project_test , afin que la base de données de développement reste intacte.

Plusieurs à plusieurs

Passons maintenant à votre problème - relation m:n entre deux modèles. Tout d'abord, du fait que vous effectuez Promise.all() , la sync peut s'exécuter dans un ordre différent de celui dans lequel vous ajoutez les fonctions. Afin d'éviter cette situation, je vous suggère d'utiliser mapSeries fonctionnalité de Bluebird promesse, que Sequelize utilise et expose sous sequelize.Promise (c'est aussi la raison de votre dernière erreur concernant la suppression de la ligne parent - vous essayez de supprimer les mentees qui est référencé à partir de menteequestion ).

sequelize.Promise.mapSeries([
    Mentee.sync({ force: true })
  , Question.sync({ force: true })
  , MenteeQuestion.sync({ force: true })
], (model) => { return model.destroy({ where: {} }); }).then(() => {

});

Premier paramètre de mapSeries est un tableau de promesses, mais la seconde est une fonction qui est exécutée avec le résultat de chaque promesse précédemment définie. En raison du fait que Model.sync() résultats dans le modèle lui-même, nous pouvons effectuer model.destroy() à chaque itération.

Après cela, vous pouvez insérer des données dans la base de données via create() , comme dans l'exemple. Il est maintenant temps de corriger l'Erreur :le mentoré n'est pas associé à la question du mentoré ! Erreur. Cela se produit parce que vous avez associé Mentee avec Question mais il n'y a pas d'association entre MenteeQuestion et Mentee (ou Question ). Afin de résoudre ce problème, après belongsToMany , vous pouvez ajouter

MenteeQuestion.belongsTo(Mentee, { foreignKey: 'menteeId' });
MenteeQuestion.belongsTo(Question, { foreignKey: 'questionId' });

Vous pouvez maintenant ajouter include: [Mentee, Question] lors de la requête MenteeQuestion . Vous exécuteriez également une autre erreur en faisant toJSON() , car vous faites findAll qui renvoie un tableau d'instances. Vous pourriez faire forEach()

menteeQuestions.forEach(menteeQuestion => {
    console.log(menteeQuestion.toJSON());
});