Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Einfaches Beispiel für eine Viele-zu-Viele-Beziehung mit Sequelize

Migrationen

Ich würde vorschlagen, dass Sie sequelize migrations verwenden stattdessen sync() ausführen bei jedem Modell. Es gibt ein Modul - sequelize.cli Damit können Sie Migrationen und Seeds einfach verwalten. Es erzwingt in gewisser Weise eine Projektstruktur, indem es die Initialisierungsdatei index.js erstellt innerhalb von /models Verzeichnis des Projektes. Es wird davon ausgegangen, dass sich alle Ihre Modelldefinitionen in diesem Verzeichnis befinden. Dieses Skript durchläuft alle Modelldateien (jede Modelldefinition befindet sich in einer separaten Datei, z. B. mentee.js , question.js ) und führt sequelize.import() aus um diese Modelle der sequelize-Instanz zuzuweisen - so können Sie später über sequelize[modelName] darauf zugreifen z.B. sequelize.question .

Hinweis: Denken Sie beim Erstellen von Migrationsdateien an Zeitstempelfelder - createdAt , updatedAt und schließlich deletedAt .

Synchronisieren

Ich persönlich verwende sync() nur wenn ich die Tests durchführe - dies kann in drei Schritten angezeigt werden

  1. Führen Sie sequelize.sync({ force: true }) aus um alle Modelle zu synchronisieren
  2. führen Sie einige Datenbank-seeds aus (kann auch über sequelize-cli erfolgen ),
  3. Tests durchführen.

Dies ist sehr komfortabel, da Sie die Datenbank vor dem Ausführen von Tests bereinigen können und Tests verschiedene Datenbanken verwenden können, um Entwicklung und Tests zu unterscheiden, z. project_test , damit die Entwicklungsdatenbank intakt bleibt.

Many-to-Many

Kommen wir nun zu Ihrem Problem - m:n-Beziehung zwischen zwei Modellen. Zunächst einmal, weil Sie Promise.all() ausführen , die sync kann in einer anderen Reihenfolge ausgeführt werden, als Sie die Funktionen darin hinzufügen. Um diese Situation zu vermeiden, schlage ich vor, dass Sie mapSeries verwenden Funktion von Bluebird Promise, das Sequelize verwendet und unter sequelize.Promise verfügbar macht (Dies ist auch der Grund für Ihren letzten Fehler beim Löschen der übergeordneten Zeile - Sie versuchen, mentees zu löschen die von menteequestion referenziert wird ).

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

});

Erster Parameter von mapSeries ist ein Array von Promises, das zweite ist jedoch eine Funktion, die mit dem Ergebnis jedes zuvor definierten Promises ausgeführt wird. Aufgrund der Tatsache, dass Model.sync() das Modell selbst ergibt, können wir model.destroy() ausführen bei jeder Iteration.

Danach können Sie einige Daten über create() in die Datenbank einfügen , genau wie im Beispiel. Jetzt ist es an der Zeit, den Fehler:Mentee ist nicht mit Mentee-Frage verknüpft! zu beheben Error. Es tritt auf, weil Sie Mentee zugeordnet haben mit Question aber es gibt keine Verbindung zwischen MenteeQuestion und Mentee (oder Question ). Um das zu beheben, nach belongsToMany , können Sie hinzufügen

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

Jetzt können Sie include: [Mentee, Question] hinzufügen bei der Abfrage von MenteeQuestion . Sie würden auch einen anderen Fehler ausführen, während Sie toJSON() ausführen , weil Sie findAll ausführen die ein Array von Instanzen zurückgibt. Sie könnten forEach() tun

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