web-dev-qa-db-fra.com

Écriture de migrations avec des clés étrangères à l'aide de SequelizeJS

L'arrière-plan

Je construis un projet avec SequelizeJS , un ORM populaire pour NodeJS. Lors de la conception d'un schéma, il semble y avoir deux tactiques:

  1. Créez le code du modèle et utilisez la fonction .sync () pour générer automatiquement des tableaux pour vos modèles.
  2. Créez le code du modèle et écrivez migrations manuelles en utilisant QueryInterface et mzug .

Ma compréhension est que le n ° 1 est meilleur pour le prototypage rapide, mais que le n ° 2 est une meilleure pratique pour les projets qui devraient évoluer dans le temps et où les données de production doivent pouvoir survivre aux migrations.

Cette question concerne la tactique n ° 2.

La (les) question (s)

Mes tables ont des relations qui doivent être reflétées par des clés étrangères.

  • Comment créer des tables avec des relations de clés étrangères entre elles via l'interface de requête Sequelize?

  • Quelles colonnes et tables auxiliaires sont requises par Sequelize? Par exemple, il apparaît que des colonnes spécifiques telles que createdAt ou updatedAt sont attendues.

23
slifty

Comment créer des tables avec des relations de clés étrangères entre elles via l'interface de requête Sequelize?

La méthode .createTable() prend un dictionnaire de colonnes. Vous pouvez voir la liste des attributs valides dans la documentation pour .define() , en particulier en regardant le [attributes.column.*] lignes dans la table params.

Pour créer un attribut avec une relation de clé étrangère, utilisez les champs "références" et "referencesKey":

Par exemple, ce qui suit créerait une table users et une table user_emails table qui référence la table des utilisateurs.

queryInterface.createTable('users', {
  id: {
    type: Sequelize.INTEGER,
    primaryKey: true,
    autoIncrement: true
  }
}).then(function() {
  queryInterface.createTable('user_emails', {
    userId: {
      type: Sequelize.INTEGER,
      references: { model: 'users', key: 'id' }
    }
  })
});

Quelles colonnes et tables auxiliaires sont nécessaires pour sequelize? Par exemple, il apparaît que des colonnes spécifiques telles que createdAt ou updatedAt sont attendues.

Il semble qu'un modèle standard attendra une colonne id, updatedAt et createdAt pour chaque table.

queryInterface.createTable('users', {
  id: {
    type: Sequelize.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  createdAt: {
    type: Sequelize.DATE
  },
  updatedAt: {
    type: Sequelize.DATE
  }
}

Si vous définissez paranoid sur true sur votre modèle, vous avez également besoin d'un horodatage deletedAt.

27
slifty

Je veux offrir une autre alternative plus manuelle parce que lors de l'utilisation des migrations manuelles et de queryInterface, j'ai rencontré le problème suivant: j'avais 2 fichiers dans le dossier de migration comme ceci

migrations/create-project.js
migrations/create-projectType.js

parce que project avait la colonne projectTypeId elle faisait référence à projectType, qui n'était pas encore créée en raison de l'ordre des fichiers et cela provoquait une erreur.

Je l'ai résolu en ajoutant une contrainte de clé étrangère après avoir créé les deux tables. Dans mon cas, j'ai décidé de l'écrire à l'intérieur create-projectType.js:

queryInterface.createTable('project_type', {
  // table attributes ...
})
.then(() => queryInterface.addConstraint('project', ['projectTypeId'], {
  type: 'FOREIGN KEY',
  name: 'FK_projectType_project', // useful if using queryInterface.removeConstraint
  references: {
    table: 'project_type',
    field: 'id',
  },
  onDelete: 'no action',
  onUpdate: 'no action',
}))
5
galki