web-dev-qa-db-fra.com

Comment définir le type de clé primaire sur UUID via Sequelize CLI

Je crée un modèle de base de données via Sequelize CLI avec cette commande:

sequelize model:create --name User --attributes "firstname:string, lastname:string"

Cela crée le script de migration correspondant:

'use strict';
module.exports = {
  up: function(queryInterface, Sequelize) {
    return queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      firstname: {
        type: Sequelize.STRING
      },
      lastname: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: function(queryInterface, Sequelize) {
    return queryInterface.dropTable('Users');
  }
};

Comme indiqué, la clé primaire est définie sur integer.

Existe-t-il un moyen de définir par défaut l'interface CLI pour utiliser UUID à la place?

11
rtorres

Vous devez modifier le fichier généré manuellement, en remplaçant Sequelize.INTEGER Par Sequelize.UUID, Puis en supprimant la propriété autoIncrement: true Et en incluant cette defaultValue: uuid().

npm install uuid

Votre modèle ressemblerait donc à ceci:

const uuid = require('uuid/v4'); // ES5

'use strict';

module.exports = {
  up: function(queryInterface, Sequelize) {
    return queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        primaryKey: true,
        type: Sequelize.UUID,
        defaultValue: uuid()
      },
      firstname: {
        type: Sequelize.STRING
      },
      lastname: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: function(queryInterface, Sequelize) {
    return queryInterface.dropTable('Users');
  }
};

Vous pouvez également retourner une fonction pour le defaultValue comme ceci:

      id: {
        allowNull: false,
        primaryKey: true,
        type: Sequelize.UUID,
        defaultValue: () => uuid()
      },

Une autre solution serait d'ajouter un crochet beforeCreate dans votre modèle.

const uuid = require('uuid/v4');

export default (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    id: {
      allowNull: false,
      primaryKey: true,
      type: Sequelize.UUID
    },
    ...
  }, {});

  User.beforeCreate(user => user.id = uuid());

  return User;
};
14
John Kennedy

La dernière réponse ne fonctionnera pas car la fonction uuid() définira une valeur par défaut unique pour tous les utilisateurs de votre base de données. Comme il s'agit d'une clé primaire, vous ne pourrez conserver qu'un seul utilisateur dans la base de données, puis tout le monde recevra la même valeur uuid et, bien sûr, ne sera pas persistant.

Alors ... vous devez:

  1. Dans votre fichier de migration, supprimez autoIncrement: true, et changez le type de votre identifiant de type: Sequelize.INTEGER à type: Sequelize.UUID
  2. Installez la fonction de générateur uuid à partir de npm i uuid --save
  3. Dans votre modèle utilisateur généré, modifiez la fonction beforeCreate pour générer un nouvel uuid avant de l'insérer dans la base de données, comme ceci:

    const uuid = require('uuid/v4');
    /*...*/
    module.exports = (sequelize, DataTypes) => {
      const User = sequelize.define('User', {
        /* Your User Model Here */
      }, {});
      User.beforeCreate((user, _ ) => {
        return user.id = uuid();
      });
      return User;
    };
    
  4. Appliquez les modifications de votre migration en procédant comme suit: sequelize db:migrate:undo suivre par sequelize db:migrate

  5. Essaye-le.

10

Vous pouvez modifier votre script de migration avec ce script

'use strict';
module.exports = {
  up: function(queryInterface, Sequelize) {
    return queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        defaultValue: Sequelize.literal('uuid_generate_v1()'),
        type: Sequelize.UUID,
      },
      firstname: {
        type: Sequelize.STRING
      },
      lastname: {
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: function(queryInterface, Sequelize) {
    return queryInterface.dropTable('Users');
  }
};

Ça marche pour moi.

3
jennndol

Vous pouvez simplement utiliser le type UUIDV4 fourni avec Sequelize. Voici plus de détails: IDV4

Par exemple, faire cette définition:

id: {
  type: Sequelize.UUID,
  defaultValue: Sequelize.UUIDV4,
  allowNull: false,
  primaryKey: true
}

Ceci n'utilise pas la CLI Sequelize mais vous pouvez utiliser cet UUIDV4 natif en le modifiant manuellement.

1
Ismael Terreno
id: {
  type: Sequelize.UUID,
  defaultValue: Sequelize.UUIDV4,
  allowNull: false,
  primaryKey: true
}

La réponse de @Ismael Terreno est vraie; cependant, il y a un bogue que je n'ai pas assez d'expérience pour expliquer: si votre modèle contient ce format tout en utilisant les exemples fournis par suite, il ne fonctionnera PAS. Même ainsi, vous n'avez pas besoin d'importer d'UUID en dehors de la suite; vous pouvez toujours profiter de la mise à disposition séquentielle, mais vous devez l'exiger pour une raison comme celle-ci:

"use strict";
module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define(
    "User",
    {
      id: {
        primaryKey: true,
        type: DataTypes.UUID,
        defaultValue: require("sequelize").UUIDV4
      },
    {}
  );
  User.associate = function(models) {
    //enter associations here
    });
  };
  return User;
};`

J'ai testé cela et cela a fonctionné, mais je ne l'ai découvert qu'en raison d'un succès précédent que j'avais eu au début, où ma configuration ressemblait à ceci pour le modèle, où j'avais tout requis avant de définir le modèle:

const { Sequelize, DataTypes, Model } = require("sequelize");
const db = require("../../config/database");

const userModel = db.define("users", {
  id: {
    type: DataTypes.UUID,
    defaultValue: Sequelize.UUIDV4,
    primaryKey: true
  }
});
0
Emanuel Siu

Si vous devez faire en sorte que Postgres génère UUID sur l'insert comme valeur par défaut, cette approche defaultValue: Sequelize.UUIDV4 Ne fonctionnera pas. Quoi qu'il en soit, Sequelize génère une valeur NULL.

À la place, Sequelize.literal('uuid_generate_v4()') doit être utilisé. Cela produira la requête CREATE TABLE IF NOT EXISTS "table" ("id" UUID NOT NULL DEFAULT uuid_generate_v4()).

id: {
    allowNull: false,
    primaryKey: true,
    type: Sequelize.DataTypes.UUID,

    defaultValue: Sequelize.literal('uuid_generate_v4()'),
},
0
Emma Paulowicz