Sequelize UUID with mySQL: Unable to set default value - mysql

I've been trying for awhile to set id (primary key) for my Users table as UUID. However, I keep getting this error: Field 'id' doesn't have a default value, when I attempt to seed it.
This is what I have so far in my Users model:
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Users extends Model {};
Users.init({
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
primaryKey: true
},
user_name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notNull: {
msg: 'Please add a name',
},
},
},
{
sequelize,
modelName: 'Users',
});
return Users;
Likewise, this is what I have in my Users migration file:
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Admins', {
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true
},
user_name: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Users');
}
};
I'm pretty new to Sequelize, so would love some guidance on what's gone wrong!

By adding defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), to your createdAt and updatedAt in your migration file defaults the value to the current timestamp.
createdAt: {
allowNull: false,
type: Sequelize.DATE,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
},

So, I think I realised the issue:
For some reason, seeding it by using a seeder file would not auto-generate the fields that I thought would be auto-generated, so I had to put them in manually.
'use strict';
const { v4: uuidv4 } = require('uuid');
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.bulkInsert('Users', [{
id: uuidv4(),
user_name: 'John Doe',
"createdAt": new Date(),
"updatedAt": new Date()
}], {});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.bulkDelete('Users', null, {});
}
};
Initially, I had been trying to seed (running the command npx sequelize-cli db:seed:all) without the id: uuidv4() and the new Date(), which was why it didn't work.

Related

Cannot find module 'sequelize/types'

anyone knows why i am getting this error
this is my code
"use strict";
const { DataTypes } = require("sequelize/types");
module.exports = {
up: async (queryInterface, DataTypes) => {
await queryInterface.createTable("dummytables", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
id: {
type: DataTypes.NUMBER,
},
first_name: {
type: DataTypes.STRING,
allowNull: false,
},
last_name: {
type: DataTypes.STRING,
allowNull: false,
},
});
},
down: async (queryInterface, DataTypes) => {
await queryInterface.dropTable("dummytables");
},
};
when am trying to run this command sequelize db:migrate
and its showing me ERROR: Cannot find module 'sequelize/types'
my dependencies file
"dependencies": {
"#types/sequelize": "^4.28.9",
"express": "^4.17.1",
"mysql2": "^2.2.5",
"sequelize": "^6.5.0",
"sequelize-cli": "^6.2.0" }
any solution need help
"use strict";
//const { DataTypes } = require("sequelize/types"); // Remove this line
module.exports = {
up: async (queryInterface, DataTypes) => {
await queryInterface.createTable("dummytables", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
id: {
type: DataTypes.NUMBER,
},
first_name: {
type: DataTypes.STRING,
allowNull: false,
},
last_name: {
type: DataTypes.STRING,
allowNull: false,
},
});
},
down: async (queryInterface, DataTypes) => {
await queryInterface.dropTable("dummytables");
},
};
If you change the second line to;
const { DataTypes } = require("sequelize");
It should work fine.
A better fix would be to just install Sequelize like;
const Sequelize = require("sequelize");
then use it like;
first_name: {
type: Sequelize.STRING,
allowNull: false,
},
You might not even need to do the importation because up() would give it to you for free, You just need to replace DataTypes with Sequelize.
async up(queryInterface, Sequelize) {
...
}
This error, may be can happen when you use auto import and it import sequelize/types, you can find in code has 'sequelize/types' and delete it in code of you should change
const {DataTypes} = require('sequelize');

ERROR: Cannot find module 'sequelize/types'

C:\Users\lenovo\Desktop\Yoobou\Yoobou>sequelize db:migrate
Sequelize CLI [Node: 14.15.1, CLI: 6.2.0, ORM: 6.3.5]
Loaded configuration file "config\config.json". Using environment
"development".
== 20201207141344-create-producteurs: migrating =======
ERROR: Cannot find module 'sequelize/types' Require stack:
C:\Users\lenovo\Desktop\Yoobou\Yoobou\migrations\20201207141344-create-producteurs.js
C:\Users\lenovo\AppData\Roaming\npm\node_modules\sequelize-cli\node_modules\umzug\lib\migration.js
C:\Users\lenovo\AppData\Roaming\npm\node_modules\sequelize-cli\node_modules\umzug\lib\index.js
C:\Users\lenovo\AppData\Roaming\npm\node_modules\sequelize-cli\lib\core\migrator.js
C:\Users\lenovo\AppData\Roaming\npm\node_modules\sequelize-cli\lib\commands\migrate.js
C:\Users\lenovo\AppData\Roaming\npm\node_modules\sequelize-cli\lib\sequelize
//MIGRATION 20201207141344-create-producteurs.js
'use strict'; const { UniqueConstraintError } =
require('sequelize/types');
module.exports = { up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('PRODUCTEURS', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
first_name: {
allowNull: false,
type: Sequelize.STRING,
unique: true,
},
last_name: {
allowNull: false,
type: Sequelize.STRING,
},
email: {
allowNull: false,
type: Sequelize.STRING,
Unique: true,
},
password: {
allowNull: false,
type: Sequelize.STRING,
},
avatar: {
allowNull: false,
type: Sequelize.STRING,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
}); }, down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('PRODUCTEURS'); }, };
// ASSOCIATION MODELS 'use strict'; const { Model } = require('sequelize'); module.exports = (sequelize, DataTypes) => {
class ADMINISTRATEUR extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The models/index file will call this method automatically.
/
associate(models) {
// define association here
models.ADMINISTRATEUR.hasMany(models.CLIENTS);
models.ADMINISTRATEUR.hasMany(models.PRODUITS);
models.ADMINISTRATEUR.hasMany(models.ADRESSE_CLIENTS);
models.ADMINISTRATEUR.hasMany(models.CATEGORY_PRODUITS);
models.ADMINISTRATEUR.hasMany(models.COMMANDES);
models.ADMINISTRATEUR.hasMany(models.PRODUCTEURS);
models.ADMINISTRATEUR.hasMany(models.AVIS);
} } ADMINISTRATEUR.init(
{
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
avatar: DataTypes.STRING,
},
{
sequelize,
modelName: 'ADMINISTRATEUR',
} ); return ADMINISTRATEUR; }; 'use strict'; const { Model } = require('sequelize'); module.exports = (sequelize, DataTypes) =>
{ class PRODUCTEURS extends Model {
/*
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The models/index file will call this method automatically.
*/
static associate(models) {
// define association here
models.PRODUCTEURS.belongsTo(models.ADMINISTRATEUR , {
foreignKey: {
allowNull: false
}
});
models.PRODUCTEURS.hasMany(models.CLIENTS);
models.PRODUCTEURS.hasMany(models.PRODUITS);
models.PRODUCTEURS.hasMany(models.ADRESSE_CLIENTS);
models.PRODUCTEURS.hasMany(models.CATEGORY_PRODUITS);
models.PRODUCTEURS.hasMany(models.COMMANDES);
} }; PRODUCTEURS.init({
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
avatar: DataTypes.STRING }, {
sequelize,
modelName: 'PRODUCTEURS', }); return PRODUCTEURS; };
I finally found the answer I had to put the variable "const {UniqueConstraintError} = require ('sequelize / types')" in comment and retype sequelize db: migrate

Sequelize - Model and Migrations

[Resolved !]
I've researched a lot on the Internet and found some similar question with mine. But, I can't find the proper way to fix my problem. Please help.
I'm using Sequelize v6. I've some troubles in using models and migrations.
What I've done:
I generated role model using sequelize cli. And it gives me below code in models/role.js.
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Role extends Model {
static associate(models) {
// define association here
}
}
Role.init(
{
name: DataTypes.STRING,
description: DataTypes.STRING, },
{
sequelize,
modelName: "roles",
}
);
return Role;
};
And I also got migration file for that model in migrations/timestamp-create-role.js.
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable(
"roles", // <- I've changed this from Roles to roles because I want the MySQL convention.
{
roleId: {
allowNull: false,
autoIncrement: true,
field: "role_id",
primaryKey: true,
type: Sequelize.INTEGER,
},
name: {
allowNull: false,
type: Sequelize.STRING(30),
},
description: {
type: Sequelize.STRING(50),
},
createdAt: {
allowNull: false,
field: "created_at",
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
field: "updated_at",
type: Sequelize.DATE,
},
},
{
underscored: true,
}
);
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("roles");
},
};
What I got in MySQL
By running the above migration, I got roles table with following columns:
role_id, name, created_at, updated_at which is fine. That is what I want in MySQL database.
Reading roles
/controllers/roles.js
const Role = require("../models").roles;
const catchAsync = require("../middlewares/catchAsync");
exports.findAll = catchAsync(async (req, res) => {
const roles = await Role.findAll();
return res.status(200).json({
status: "success",
data: {
roles,
},
});
});
What I'm not OK
With the above implementation, I got this error on the console.
Executing (default): SELECT `id`, `name`, `description`, `createdAt`, `updatedAt` FROM `roles` AS `roles`;
SequelizeDatabaseError: Unknown column 'id' in 'field list'
at Query.formatError (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/mysql/query.js:239:16)
at Query.run (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/mysql/query.js:54:18)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async /home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/sequelize.js:619:16
at async MySQLQueryInterface.select (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/abstract/query-interface.js:938:12)
at async Function.findAll (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/model.js:1741:21)
at async /home/hello-world/Thesis/SMS-API/src/controllers/roles.js:5:17
at async /home/hello-world/Thesis/SMS-API/src/middlewares/catchAsync.js:4:7
Another Attempt
I've modified models/role.js like below.
Role.init(
{
role_id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
name: DataTypes.STRING,
description: DataTypes.STRING,
created_at: DataTypes.DATE,
updated_at: DataTypes.DATE,
}
Next try, Next Error
With the above modification, I got new error.
Executing (default): SELECT `role_id`, `name`, `description`, `created_at`, `updated_at`, `createdAt`, `updatedAt` FROM `roles` AS `roles`;
SequelizeDatabaseError: Unknown column 'createdAt' in 'field list'
at Query.formatError (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/mysql/query.js:239:16)
at Query.run (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/mysql/query.js:54:18)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async /home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/sequelize.js:619:16
at async MySQLQueryInterface.select (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/dialects/abstract/query-interface.js:938:12)
at async Function.findAll (/home/hello-world/Thesis/SMS-API/node_modules/sequelize/lib/model.js:1741:21)
at async /home/hello-world/Thesis/SMS-API/src/controllers/roles.js:5:17
at async /home/hello-world/Thesis/SMS-API/src/middlewares/catchAsync.js:4:7
HELP
I've tried so many ways which cannot fix my problem yet. So, please help. I want MySQL naming convention in MySQL level which is underscore and JavaScript naming convention in Code level.
Thank you so much.
I've fixed my problem. I can now use each naming convention for their specific world: under_score for MySQL and camelCase for JavaScript.
So here I've written my solution if someone come across the same issue in the future.
I'm using sequelize-cli for creating migrations, models and seeders. You can check it here.
Migration
Migration is only responsible for creating/altering/deleting the tables and columns. It access with only the database.
migrations/timestamp-create-role-table.js
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("roles", {
roleId: {
allowNull: false,
autoIncrement: true,
field: "role_id",
primaryKey: true,
type: Sequelize.INTEGER,
},
name: {
allowNull: false,
type: Sequelize.STRING(30),
},
description: {
type: Sequelize.STRING(50),
},
createdAt: {
allowNull: false,
field: "created_at",
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
field: "updated_at",
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("roles");
},
};
By running the above migration script, I got the roles table with following columns in my physical database.
role_id, name, description, created_at, updated_at
Seeder
Seeder will populate your table with initial test data. I've filled my roles table like below.
seeders/timestamp-roles-table-seeder.js
"use strict";
const roles = [
"official",
"office",
"admin"
].map((role) => {
return {
name: role,
created_at: new Date(),
updated_at: new Date(),
};
});
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.bulkInsert("roles", roles);
},
down: async (queryInterface, Sequelize) => {
await queryInterface.bulkDelete("roles", null, {});
},
};
Model
After I've created table and filled up with initial data, I need to create Role model in order to use as bridge between MySQL and JavaScript.
models/role.js
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Role extends Model {
static associate(models) {
// define association here
}
}
Role.init(
{
roleId: {
allowNull: false,
autoIncrement: true,
field: "role_id", // SELECT role_id AS id
primaryKey: true,
type: DataTypes.INTEGER,
},
name: DataTypes.STRING,
description: DataTypes.STRING,
createdAt: {
type: DataTypes.DATE,
field: "created_at",
},
updatedAt: {
type: DataTypes.DATE,
field: "updated_at",
},
},
{
sequelize,
tableName: "roles",
modelName: "Role",
}
);
return Role;
};
Getting roles from JavaScript
controllers/roles.js
const models = require("../models");
const catchAsync = require("../middlewares/catchAsync");
exports.findAll = catchAsync(async (req, res) => {
const roles = await models.Role.findAll();
/*
you can access
- role_id from db with roleId in JS
- created_at from db with createdAt in JS
*/
return res.status(200).json({
status: "success",
data: {
roles,
},
});
});
Hope it could help!

Unable to insert id into a table that belongs to a foreign key referenced table using Sequelize

I am building serverless application using node js and using claudia-api-builder as a framework to launch APIs in AWS.
In app.js file, i call the required api as
const ApiBuilder = require('claudia-api-builder');
const api = new ApiBuilder();
module.exports = api;
api.post('/api/auth/validatephonenumber', async function (request)
{
return new Promise((resolve, reject) => {
index.loadDatabase().then((db) => {
resolve(loginController.validatePhonenumber(db, request));
});
});
});
Below is my code:
async function validatePhonenumber(db, request) {
return new Promise(
async (resolve, reject) => {
let emailid;
await db.EmailRegistration.sync().then(function () {
emailid = db.EmailRegistration.findOne({
where: { email: { [Op.eq]: mailid } },
attributes: ['id'],
});
});
if (emailid != null) {
console.log(`email id: ${emailid.id}`);
await db.ContactDetails.sync().then(function () {
db.ContactDetails.findOrCreate({
where: { contactnumber: phnum },
defaults: { EmailRegistrationId: emailid.id },
}).spread((contactdetails, created) => {
console.log(`contactdetails: ${contactdetails}`);
if (contactdetails !== null) {
resolve({ statuscode: indexController.statusCode.statusOK, contactdetails: contactdetails })
} else {
reject({ statuscode: indexController.statusCode.InternalServerError, message: 'phone number not created' });
}
});
});
};
});
}
I am trying to add a emailregistrationid of EmailRegistration table into ContactDetails table as a foreign key reference. I am using sequelize with mysql, nodejs to achieve the desired results. But, i am getting below error:
Unhandled rejection SequelizeForeignKeyConstraintError: Cannot add or update a child row: a foreign key constraint fails (inmeeydb.ContactDetails, CONSTRAINT ContactDetails_ibfk_1 FOREIGN KEY (EmailRegistrationId) REFERENCES EmailRegistration (id) ON DELETE CASCADE ON UPDATE CASCADE)
Below is my EmailRegistration models file:
const moment = require('moment');
module.exports = (sequelize, DataTypes) => {
const EmailRegistration = sequelize.define(
'EmailRegistration',
{
id: {
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
},
email: {
type: DataTypes.STRING(50),
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
validate: { min: 6 },
},
createdAt: {
type: DataTypes.DATE,
get() {
return moment.utc(new Date(), 'DD/MM/YYYY h:mm a').format('DD/MM/YYYY h:mm a');
},
},
updatedAt: {
type: DataTypes.DATE,
defaultValue: null,
},
},
{
freezeTableName: true,
}
);
EmailRegistration.associate = function (models) {
EmailRegistration.hasOne(models.ContactDetails,
{ foreignKey: 'EmailRegistrationId' }
);
};
return EmailRegistration;
};
Below is my Contactdetails models file:
const moment = require('moment');
module.exports = (sequelize, DataTypes) => {
const ContactDetails = sequelize.define(
'ContactDetails',
{
id: {
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
},
contactnumber: { type: DataTypes.STRING(13), allowNull: false },
isverified: { type: DataTypes.BOOLEAN, defaultValue: false },
createdAt: {
type: DataTypes.DATE,
get() {
return moment.utc(new Date(), 'DD/MM/YYYY h:mm a').format('DD/MM/YYYY h:mm a');
},
},
updatedAt: {
type: DataTypes.DATE,
defaultValue: null,
},
},
{
indexes: [{ fields: ['contactnumber'], unique: true }],
},
{
freezeTableName: true,
}
);
ContactDetails.associate = function(models) {
ContactDetails.belongsTo(models.EmailRegistration, {
onDelete: 'CASCADE',
hooks: true,
foreignKey: { allowNull: false },
});
};
return ContactDetails;
};
I tried to change the code as below with reference in both tables, but nothing worked.
ContactDetails.associate = function(models) {
ContactDetails.belongsTo(models.EmailRegistration,
{ foreignKey: 'EmailRegistrationId' }
);
};
Not able to analyze how to overcome the issue. This worked fine when i used nodejs with expressjs and had no issues. It fails to identify the EmailRegistrationId(that is missing in the query) in ContactDetails table and shows the output as
INSERT INTO `ContactDetails` (`id`,`contactnumber`,`isverified`,`createdAt`,`updatedAt`) VALUES ('52974e07-8489-4101-ab71-6af874903290','+xxxxxxxxx',false,'2018-10-12 08:55:35','2018-10-12 08:55:35');
You need to update the configuration of your association. The ContactDetails model will now have a field called emailregistrationid
EmailRegistration.associate = function (models) {
EmailRegistration.hasMany(models.ContactDetails);
};
ContactDetails.associate = function(models) {
ContactDetails.belongsTo(models.EmailRegistration, {
onDelete: 'CASCADE',
hooks: true,
foreignKey: {
name: 'emailregistrationid'
allowNull: false
},
});
}
ContactDetails.create({
...
emailregistrationid: <some_valid_emailregistrationid>
})

why model not fetching all attributes in table in sequelize

I have created model for my databse and then run migration it successfully created the table in database after this I create migration to add column to that existing table . When I run model.findall query it only gets the attributes that I created first time e.g here is my model file
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('ActiveUsers', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
username: {
type: Sequelize.STRING
},
name: {
type: Sequelize.STRING
},
socketId: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('ActiveUsers');
}
};
here is migration file to add column to this table
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
queryInterface.addColumn(
'ActiveUsers',
'Token',
{
type: Sequelize.STRING,
allowNull: false
}
)
},
down: (queryInterface, Sequelize) => {
}
};
here is table pic
it only gets the attributes that are present in model file i.e
username,name,socketId,updatedAt,createdAt
why it dont get the value of
token,status
here is my code
activeusers.findAll({raw:true}).then(Users=>{
console.log('online users')
})
The first file you wrote is not a model file, it is a migration file. If you want to select your new fields you should add them to your model file.
Your model file should look like this:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('activeUsers', {
id: {
type: DataTypes.STRING,
allowNull: false,
primaryKey: true,
unique: true
},
username: {
type: Sequelize.STRING
},
name: {
type: Sequelize.STRING
},
socketId: {
type: Sequelize.STRING
},
token: {
type: Sequelize.STRING
},
status: {
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
};
You can read more in Sequelize docs about how to add models to your project.
We have to add column fields to model file manually . then it will fetch that fields