'How to set primary key type to UUID via Sequelize CLI
I'm creating a DB model via Sequelize CLI with this command:
sequelize model:create --name User --attributes "firstname:string, lastname:string"
This creates the corresponding migration script:
'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');
}
};
As shown, the primary key is set to integer
.
Is there a way to default the CLI to use UUID
instead?
Solution 1:[1]
You can simple use the type UUIDV4 that comes with Sequelize. Here is more details : UUIDV4
For example making this definition:
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true
}
This is not using the Sequelize CLI but you can use that native UUIDV4 by manually changing that.
Solution 2:[2]
You'd have to edit the generated file manually, changing Sequelize.INTEGER
to Sequelize.UUID
, then remove the autoIncrement: true
.
npm install uuid
So your model would look like this:
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
},
/* Other model properties */
});
},
down: function(queryInterface, Sequelize) {
return queryInterface.dropTable('Users');
}
};
Update your beforeCreate
hook as follows:
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;
};
This assumes you are using Sequelize v4.
Solution 3:[3]
The last answer will not work because the uuid()
function will set a unique default value for all users in your database. Since they are a primaryKey, you will be able to persist only one user in the database, then everyone will receive the same uuid value and, of course, will not be persisted.
So... You have to:
- In your migration file, remove
autoIncrement: true,
and change the type of your id fromtype: Sequelize.INTEGER
totype: Sequelize.UUID
- Install the uuid generator function from
npm i uuid --save
In your generated User Model, change the
beforeCreate
function to generate a new uuid before insert it in the database, like this: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; };
Apply the changes of your migration by doing:
sequelize db:migrate:undo
follow bysequelize db:migrate
Test it.
Solution 4:[4]
You can modify your migration script with this script
'use strict';
module.exports = {
up: function(queryInterface, Sequelize) {
return queryInterface.createTable('Users', {
id: {
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.literal('uuid_generate_v4()')
},
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');
}
};
It works for me.
Solution 5:[5]
Any of the solutions mentioned above did not work for me. But was much helpful to arrive on my own resolution of the problem.
I'm using ES6+ syntax and solved this way:
PS: Sequelize on v5.x
Migration
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('users', {
id: {
type: Sequelize.UUID,
primaryKey: true,
allowNull: false,
defaultValue: Sequelize.UUIDV4,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
created_at: {
type: Sequelize.DATE,
allowNull: false,
},
updated_at: {
type: Sequelize.DATE,
allowNull: false,
}
});
},
down: (queryInterface) => {
return queryInterface.dropTable('users');
}
}
Model
import { uuid } from 'uuidv4';
import Sequelize, { Model } from 'sequelize';
class User extends Model {
static init(sequelize) {
super.init(
{
name: Sequelize.STRING,
},
{
sequelize,
}
);
this.addHook('beforeSave', async (user) => {
return user.id = uuid();
});
return this;
}
}
export default Users;
Controller
import User from '../models/User';
class UserController {
async store(request, response) {
const { user } = request.body;
const { id, name } = await User.create(users);
return response.json({
id,
message: `User ${name} was register successful`,
});
}
Solution 6:[6]
If you need to make Postgres generate UUID on the insert as a default value,
this approach defaultValue: Sequelize.UUIDV4
would not work. Anyway, Sequelize generates NULL value.
Instead, Sequelize.literal('uuid_generate_v4()')
must be used.
That shall produce query 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()'),
},
Solution 7:[7]
- No auto increment. UUID are randomly generated.
- Ensure you use
DataType.UUID
and default value toUUIDV4
No Auto increment. UUID are generated
export const User = db.define('user',
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
Solution 8:[8]
I tried many options, everything turned out to be very simple. Try like this
Model:
import { Model, DataTypes } from 'sequelize';
import { v4 as uuidv4 } from 'uuid';
import sequelize from '..';
class User extends Model {}
User.init(
{
id: {
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
defaultValue: () => uuidv4(),
}
},
{
sequelize,
tableName: 'user',
timestamps: false,
},
);
export default User;
Migration:
const { v4: uuidv4 } = require('uuid');
module.exports = {
up: async (queryInterface, DataTypes) => {
await queryInterface.createTable('user', {
id: {
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
defaultValue: uuidv4(),
}
});
},
down: async queryInterface => {
await queryInterface.dropTable('user');
},
};
Solution 9:[9]
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true
}
The answer from @Ismael Terreno is true; however, there is a bug that I'm not experienced enough to explain: if your model contains that format while using the examples provided from sequelize it will NOT work. Even so, you don't need to import UUID outside of sequelize; you can still take advantage of sequelize providing it, but you have to require it in for some reason like so:
"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;
};`
I tested that and it worked, but I only found this out because of a previous success I had early on where my set up looked like this for the model, where I required everything before defining the model:
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
}
});
Solution 10:[10]
Make sure your package.json has updated uuid module
"uuid": "^8.2.0",
This was the problem in my case as it was 3.4.0
before and sequelize does not work with that.
accessSecret: {
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
unique: true,
},
This works just fine after the uuid package upgrade on MySQL
Don't forget to change your imports to
const { v4: uuid } = require('uuid')
Tested on "sequelize": "^5.21.13"
Solution 11:[11]
simply and work for all databases
const uuidv4 = require('uuid/v4');
id: {
type: DataTypes.UUID,
unique: true,
primaryKey: true,
isUUID: 4,
defaultValue: uuidv4()
},
Solution 12:[12]
For sequelize v6.5.0
using Postgres specifying defaultValue: Sequelize.UUIDV4
did not work. Instead I had to do this:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.sequelize.query('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";')
await queryInterface.addColumn('MyTable', 'id', {
type: Sequelize.UUID,
defaultValue: Sequelize.literal('uuid_generate_v4()'),
allowNull: false,
primaryKey: true
})
},
down: async (queryInterface, Sequelize) => {
}
};
Solution 13:[13]
To set the default value in migration you will need to write like this
id: {
primaryKey: true,
allowNull: false,
defaultValue: Sequelize.literal("gen_random_uuid()"),
type: Sequelize.UUID,
},
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow