nodejs sequelize: I can't update the primary key field's value - mysql

I can update every field's value except the id (primary key). It's for a website. I want to be able to update the id via the website.
module.exports = {
schema: function (sequelize, DataTypes) {
return sequelize.define(
'T_Event',
{
id: {
type: DataTypes.STRING,
primaryKey: true
},
user_id: {
type: DataTypes.STRING
},
name: {
type: DataTypes.STRING
},
created_at: {
type: DataTypes.DATE
},
description: {
type: DataTypes.STRING
},
image: {
type: DataTypes.STRING
},
closed_at: {
type: DataTypes.DATE
}
},
{
timestamps: true,
paranoid: true,
underscored: true,
freezeTableName: true
}
)
}
I'm using sequelize 3.33.0 with node and a MySQL database.
All attributes have select,insert & update privileges.

Sequelize restricts this kind of operation for security reasons. Usually updating a primary key through runtime with user provided information is a bad idea. It can lead to all sort of issues, especially if the changed object is being used by other users at the moment.
I follow the rule of thumb: if the column value can be changed, it is not a good candidate for a primary key. If there is no good candidate among all columns, create one with this sole purpose.
schema: function (sequelize, DataTypes) {
return sequelize.define(
'T_Event',
{
uid: {
type: DataTypes.BIGINT,
primaryKey: true,
autoIncrement: true
},
id: {
type: DataTypes.STRING,
unique: true
},
// ...
)
}
That said, there are cases where this kind of solution isn't doable. In that case, you may use a workaround, making an update that changes the id:
T_Event.update(
{
id: new_value
}, {
where: {
uid: current_value
}
}
);

Related

How to add foreign key using sequelize mysql

"I have 2 tables "Users" and "Profile_personals". How do I add a foreign key constraint to my profile personals using my "user_id" primary that's inside my Users table? I'm working with node.js, sequelize mysql.
Users(parent Table):
const Sequelize = require('sequelize')
const db = require("../database/db.js")
module.exports = db.sequelize.define(
"users",
{
user_id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
}
},
{
timestamps: false
}
)
Personals(Child Table):
const Sequelize = require('sequelize')
const db = require("../database/db.js")
module.exports = db.sequelize.define(
'profile_personals',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
biography: {
type: Sequelize.STRING
}
},
{
timestamps: false
}
)
Do it this way, I hope it's what you're looking for.
module.exports = db.sequelize.define(
'profile_personals',
{
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
biography: {
type: Sequelize.STRING
},
// It is possible to create foreign keys:
user_id: {
type: Sequelize.INTEGER,
references: {
// This is a reference to another model
model: Users,
// This is the column name of the referenced model
key: 'user_id'
}
}
},
{
timestamps: false
}
);

Sequelize primaryKey as UUID in MySql database - not working

I'm facing the problem with implementation model in Sequalize with primary key as uuid. I follow step by step all instruction, but still I cannot solve it.
This is how my model looks like:
'use strict';
module.exports = (sequelize, DataTypes) => {
var Todo = sequelize.define('Todo', {
title: DataTypes.STRING,
description: DataTypes.STRING,
test: DataTypes.UUID
}, {});
Todo.associate = function(models) {
// associations can be defined here
};
return Todo;
};
And migration file:
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Todos', {
id: {
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV1
},
title: {
type: Sequelize.STRING
},
description: {
type: Sequelize.STRING
},
test: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Todos');
}
};
After calling post method to create element, I habe got an empty value in ID column, and NULL in test column...
The Datebase is MySql.
Is there any other way to do it?
1) Setting Custom Keys in Sequelize
I'm facing the problem with implementation model in Sequalize with
primary key as uuid.
By default, if your model does not contain a key with primaryKey: true, then sequelize assumes a PK of type INTEGER named id.
In your case, it seems like you wish to make your own custom PK.
Use the following in your model:
var Todo = sequelize.define('Todo', {
id: {
primaryKey: true,
type: DataTypes.UUID
}
// rest of properties
});
2) Validations
After calling post method to create element, I habe got an empty value in ID column, and NULL in test column...
Without much information regarding not only your query, but how you seeded the database, it's hard to answer specifically.
However, it doesn't surprise me that test column was null, because you have not listed any validations. Thus if you seed/create rows that do not set a test value, it will be null.
To create validations do the following
model:
var Todo = sequelize.define('Todo', {
// rest of properties
test: {
allowNull: false
type: DataTypes.UUID,
validate: {
notNull: true
}
}
});
migration:
queryInterface.createTable('Todos', {
// rest of properties
test: {
allowNull: false,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4
}
});
3) Keeping Models and Migrations Synchronized
(see: https://stackoverflow.com/a/49796801/8954866) In sequelize, models and migrations are not automatically in-sync with one another, except when initially generated using sequelize-cli model:generate. I'm unsure if you ran your migrations or if you were running your query in a unit test against the model. But you have to make sure they are synchronized. A primary example is that in the above case, your migration says id is of type UUID, but your model will think it's of type INTEGER.
References
Setting Custom Primary Keys
Validations and allowNull
Make sure your package.json has updated uuid module, this was the problem in my case.
accessSecret: {
type: DataTypes.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
unique: true,
},
This works fine,
just make sure package.json has
"uuid": "^8.2.0",
Looks like this issue is the same for both MySQL and Postgres: Sequelize needs to use the defaultValue setting of the model to point to its uuid dependency.
For example, for an entity called Product, create your migration like this:
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("Products", {
id: {
type: Sequelize.UUID,
primaryKey: true,
defaultValue: Sequelize.UUIDV4,
},
productName: {
type: Sequelize.STRING,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("Products");
},
};
Then, create your model like this:
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Product extends Model {
static associate(models) {
// associations
}
}
Product.init(
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
productName: DataTypes.STRING,
},
{
sequelize,
modelName: "Product",
}
);
return Product;
};
Note that in your model, you're defining defaultValue: DataTypes.UUIDV4.
When you create a new instance of Product, you only need the name field. The UUID is auto-generated by the Sequelize model.
const {
Product
} = require("./models");
const createProduct = async (name) => {
const newProductData = { productName: "First product" };
const creationResult = await Product.create(newProductData);
};
The id field in the model will trace the defaultValue setting back to the v4() function of the uuid package that Sequelize relies on to auto-generate the UUID as part of the model operation, not as part of native Postgres.

Sequelize 4 - belongs-To-Many insert issue on eagger loading

Hi Folks, I have these two models:
const media = sequelize.define('media', {
id: { type: Sequelize.UUID, primaryKey: true, defaultValue: Sequelize.UUIDV4 },
name: { type: Sequelize.STRING, allowNull: false, unique:'compositeIndex' },}, { freezeTableName: true });
const mediaGenre = sequelize.define('mediaGenre', {
id: { type: Sequelize.UUID, primaryKey: true, defaultValue: Sequelize.UUIDV4 }}, { freezeTableName: true, name: { plural: 'mediaGenre' } });
and these two relations:
media.hasMany(mediaGenre, as: 'mGenre');
mediaGenre.belongsTo(media);
media.belongsToMany(genre, { through: mediaGenre });
genre.belongsToMany(media, { through: mediaGenre });
when I want to create a media I do:
MediaModels.media.create(
{name: 'Hulk',
mediaGenre: [
{ genreId: '021baab5-7fc6-4b06-aca5-e4b1ed1f3ce4' },
{ genreId: '03f069a4-dc52-4ab5-82d3-6bcd67d2d29e' }]},
{
include: [
{model: MediaModels.mediaGenre, as: 'mGenre'}
]
}
);
These has been working with sequelize 3 and recently I updated to sequelize 4.4.2 and it is not throwing error but the table mediaGenre it's not been populated.
Any ideas of what could be the error?
Have you tried to sync after you referenced the association? I had this issue and when i called to sync (with force false, this is important if tou dont want to erase your schema and to be recreated), the junction table was created.
If you are using sequelize-cli,also notice that in this version, classMethods are not longer supported. Instead, you shold add a method called associate directly to your model, which will be called in your models/index.js.

Sequelizejs, how sort field values when creating an index

I have some 'invite' model:
'use strict';
export default function (sequelize, DataTypes) {
return sequelize.define('Invite', {
userFromId: {
type: DataTypes.INTEGER,
modal: 'User',
key: '_id',
onDelete: 'cascade'
},
userToId: {
type: DataTypes.INTEGER,
modal: 'User',
key: '_id',
onDelete: 'cascade'
},
accept1: {
type: DataTypes.BOOLEAN,
defaultValue: false
},
accept2: {
type: DataTypes.BOOLEAN,
defaultValue: false
}
},{
indexes: [
{
name:'id',
unique: true,
fields: ['userFromId','userToId'],
}]
}
);
}
I need that when i to create a new 'Invite', a combination of 'userFromId' and 'userToId' created one index regardless of who gets invited. For example invite {userFromId:1,userToId:2} and {userFromId:2,userToId:1} must have the same index.
I use sequelize: 3.29.0 and mysql.
This is not possible using a database index because [1, 2] != [2, 1]. If you want to enforce this type of uniqueness one option is to create a new field with a unique index and set it's value to be lower + : + higher so that in the example above you always end up with 1:2.
// Create a field called 'uniqueKey' set to the sorted IDs
export default function (sequelize, DataTypes) {
return sequelize.define('Invite', {
// ... other fields
uniqueKey: {
type: DataTypes.String,
allowNull: false,
defaultValue: function() {
// create an array of the IDs, sort, then join with :
return [
this.getDataValue('userFromId'),
this.getDataValue('userToId'),
].sort().join(':');
},
},
// ... other fields
},{
indexes: [
{
name:'uniqueKey',
unique: true,
fields: ['uniqueKey'],
}]
}
);
}
You can see how the defualtValue is calculated here, the key/result is the same regardless of the order of IDs:
[1,2].sort().join(':');
"1:2"
[2,1].sort().join(':');
"1:2"

Set safe-deleting mode for relations table in Sequelize.js

So, assume we have that Sequelize model:
var User = sequelize.define("User", {
id: {
type: DataTypes.STRING(45),
allowNull: false,
primaryKey: true
},
password: {
type: DataTypes.STRING(60),
allowNull: false
},
email: {
type: DataTypes.STRING(45),
allowNull: false,
unique: true
},
firstName: {
type: DataTypes.STRING(45),
allowNull: true,
defaultValue: null
}
},
{
tableName: 'profiles',
classMethods: {
associate: function(models) {
User.belongsToMany(User, {through: 'friends', as:'friend'});
}
}
});
after calling associate() method, it will create an extra table friends with columns userId, friendId, createdAt and updatedAt. The case is I need to use this table with safe-deleting mode, in other words, I have to add 'deleted' column somehow. I tried to use paranoid: true in belongsToMany's attributes, didn't work. Is there any ways to do it?
Maybe you can create an model/table which name is Friend. And you can set paranoid: true in that model. And when you deleted an User, it keeps User's friend relation was keeping in that model.
I hope it works. :)