I am trying to write a migration in Sequelize and MySQL, which sets the unique attribute to false. This is my approach so far:
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.changeColumn("users", "name", {
type: Sequelize.STRING,
allowNull: false,
unique: true,
});
await queryInterface.changeColumn("users", "email", {
type: Sequelize.STRING,
allowNull: false,
unique: true,
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.changeColumn("users", "name", {
type: Sequelize.STRING,
allowNull: true,
unique: false,
});
await queryInterface.changeColumn("users", "email", {
type: Sequelize.STRING,
allowNull: true,
unique: false,
});
},
};
The up migration works like charme, the down migration works for allowNull, but not for unique attribute. I am new to Sequelize so I am wondering, what is going wrong here. Can someone help me out?
Thank you very much in advance.
Sequelize has "removeConstraint" method, using which you will be able to remove the constraint for the attribute.
public removeConstraint(tableName: string, constraintName: string, options: Object): Promise
Actually, if you don't specify the "constraintName" in creating, it should be of the form "attributename_unique_key".
Please try using this way
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.changeColumn("users", "name", {
type: Sequelize.STRING,
allowNull: false,
unique: true,
});
await queryInterface.changeColumn("users", "email", {
type: Sequelize.STRING,
allowNull: false,
unique: true,
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.changeColumn("users", "name", {
type: Sequelize.STRING,
allowNull: true,
});
await queryInterface.removeConstraint("users", "name_unique_key");
await queryInterface.changeColumn("users", "email", {
type: Sequelize.STRING,
allowNull: true,
});
await queryInterface.removeConstraint("users", "email_unique_key");
},
};
For more information please check the documentation here
Related
I'm trying to seed into a database. I have successfully seeded using 2 other models, but when I try to seed data into a Model called 'Comment', I get this error:
TypeError: this.sequelize.isDefined is not a function
It has only happened for this particular model, even though the syntax is practically identical to the other two. Has anyone gotten this error before?
Here is the seed.js file. I commented out the Comment section (the one that doesn't work) but the other two are just fine.
const sequelize = require('../config/connection');
const { User, Post, Comment } = require('../models');
const userData = require('./usersSeed.json');
const postData = require('./postsSeed.json');
const commentData = require('./commentSeed.json')
const seedDatabase = async () => {
await sequelize.sync({ force: true });
await User.bulkCreate(userData, {
individualHooks: true,
returning: true,
});
await Post.bulkCreate(postData, {
individualHooks: true,
returning: true,
});
/* await Comment.bulkCreate(commentData,
{
individualHooks: true,
returning: true,
}); */
process.exit(0);
};
seedDatabase();
Here is a model that works fine
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/connection');
class Post extends Model {}
Post.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
post_title: {
type: DataTypes.TEXT,
allowNull: false
},
post_text: {
type: DataTypes.TEXT,
allowNull: true,
},
user_id: {
type: DataTypes.INTEGER,
references: {
model: 'user',
key: 'id'
}
},
date_posted: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
}
},
{
sequelize,
timestamps: false,
freezeTableName: true,
underscored: true,
modelName: 'post',
}
)
module.exports = Post;
Here is the Comment model
const { Model, DataTypes } = require('sequelize');
const sequelize = require('sequelize');
class Comment extends Model {}
Comment.init(
{
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
comment_text: {
type: DataTypes.TEXT,
allowNull: false
},
post_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'post',
key: 'id'
}
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'user',
key: 'id'
}
}
},
{
sequelize,
timestamps: false,
freezeTableName: true,
underscored: false,
modelName: 'comment'
}
)
module.exports = Comment;
Here is the index for the Models
const User = require('./User');
const Post = require('./Post');
const Comment = require('./Comment')
User.hasMany(Post, {
foreignKey: 'user_id'
});
Post.belongsTo(User, {
foreignKey: 'user_id',
});
Comment.belongsTo(User, {
foreignKey: 'user_id'
});
Comment.belongsTo(Post, {
foreignKey: 'post_id'
});
User.hasMany(Comment, {
foreignKey: 'user_id'
});
Post.hasMany(Comment, {
foreignKey: 'post_id'
});
module.exports = { User, Post, Comment};
Wow so dumb. I needed to change the sequelize variable to require the connection
const sequelize = require('../config/connection');
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.
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');
20181005120552-create-order-detail.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('OrderDetails', {
orderDetailId: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
autoIncrement: true,
},
orderId: {
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
references: {
model: 'Orders',
key: 'orderId'
}
},
productName: {
type: Sequelize.STRING,
primaryKey: true,
allowNull: false,
},
count: {
type: Sequelize.INTEGER
},
orderDetailPrice: {
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
references: {
model: 'Orders',
key: 'totalPrice'
}
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('OrderDetails');
}
};
20181005120522-create-order
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface
.createTable('Orders', {
orderId: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
userId: {
type: Sequelize.STRING,
onDelete: 'CASCADE',
references: {
model: 'Users',
key: 'userId'
}
},
orderDate: {
type: Sequelize.DATE
},
totalPrice: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
},
orderState: {
type: Sequelize.STRING
},
shippingNumber: {
type: Sequelize.STRING
},
basicAddress: {
type: Sequelize.STRING
},
detailAddress: {
type: Sequelize.STRING
},
telNumber: {
type: Sequelize.INTEGER
},
phoneNumber: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Orders');
}
};
When i executed script sequelize db:migrate, previous migration is without errors executed. in this level it returns error. I don't know how can i resolve this problem i guess it has something wrong.
ERROR: Failed to add the foreign key
constraint. Missing index for
constraint 'orderdetails_ibfk_2' in
the referenced table 'orders'
This is error message. I wanna connect files OrderDetails.orderDetailPrice and Orders.totalPrice.
Thanks.
As reported here, it seems that Sequelize has some issues with references to composite keys.
However, by exploiting the Sequelize query execution you can workaround you problem. In you case you can perform the following mysql query:
ALTER TABLE `db_test`.`OrderDetails` ADD CONSTRAINT `fk_order_detailes_orders`
FOREIGN KEY (`orderId` , `orderDetailId`)
REFERENCES `db_test `.`orders`(`orderId` , `totalPrice`);
So your create-order-detail migration file becomes the following:
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('OrderDetails', {
orderDetailId: {
type: Sequelize.INTEGER.UNSIGNED,
primaryKey: true,
allowNull: false,
autoIncrement: true,
},
orderId: {
type: Sequelize.INTEGER,
allowNull: false,
},
productName: {
type: Sequelize.STRING,
primaryKey: true,
allowNull: false,
},
count: {
type: Sequelize.INTEGER,
},
orderDetailPrice: {
type: Sequelize.INTEGER,
allowNull: false,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
})
.then(() => {
return queryInterface.sequelize.query('ALTER TABLE `OrderDetails` ADD ' +
'CONSTRAINT `fk_order_details_orders` FOREIGN KEY (`orderId`, `orderDetailPrice`) REFERENCES ' +
'Orders(`orderId`, `totalPrice`)');
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('OrderDetails', null);
},
};
Giordano,
I defined this way the code is below. Let me know why this code can be migrated? primary key and unique key both keys are written though..
create-order-detail.js
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('OrderDetails', {
(...),
productName: {
type: Sequelize.STRING,
primaryKey: true,
// allowNull: false
unique: true
},
count: {
type: Sequelize.INTEGER
},
orderDetailPrice: {
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
// references: {
// model: 'Orders',
// key: 'totalPrice'
// }
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
})
.then(() => {
queryInterface.addConstraint('OrderDetails', ['orderDetailPrice'], {
type: 'foreign key',
references: {
name: 'orderdetails_ibfk_2',
table: 'Orders',
field: 'totalPrice'
},
})
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('OrderDetails');
}
};
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