PostgreSQL does not post a field - node.js

I'm currently running through using Node-Express and Sequelize as the ORM for PostgreSQL. I am trying to test my API route when I noticed that my todoId is not being returned. When I check my table I see a null value even though I have allowNull:false set.
module.exports = {
up: (queryInterface, Sequelize) =>
queryInterface.createTable('TodoItems', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
content: {
type: Sequelize.STRING,
allowNull: false,
},
complete: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
todoId: {
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
allowNull: false,
references: {
model: 'Todos',
key: 'id',
as: 'todoId',
},
},
}),
down:(queryInterface/*, Sequelize*/) => queryInterface.dropTable('TodoItems'),
};
I have tried everything from dropping my database and creating a new one and migrations for the schema all over again. What I'm trying to achieve is to ensure that the value of the todoId column references and maps my the id of a separate table called todo.

Solved it. The error was using a deprecated class methods

Related

Sequelize. How to set OnUpdate to NO ACTION when creating a foreign key with migration

I'm new to nodejs. I have created a template with expressJs. For migration and ORM purposes I am using squelizeJs with mysql2 plugin. I have created migrations and models for my tables. But I could not change the default behavior when creating foreign keys, which is to change the values of onUpdate and onDelete
How can I implement this SQL query inside sequelize migration?
CONSTRAINT `fk_keywords_2`
FOREIGN KEY (`bot_id`)
REFERENCES `mydb`.`bots` (`id`)
ON DELETE RESTRICT
ON UPDATE NO ACTION)
I have tried
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('Keywords', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER.UNSIGNED
},
bot_id: {
allowNull: false,
type: Sequelize.INTEGER.UNSIGNED,
references: {
model: 'Bots',
key: 'id'
},
onUpdate: 'NO ACTION',
onDelete: 'RESTRICT'
},
parent_id: {
type: Sequelize.INTEGER.UNSIGNED
},
keyword: {
allowNull: false,
type: Sequelize.STRING
},
time_duration: {
type: Sequelize.STRING
},
is_all_message_config: {
allowNull: false,
type: Sequelize.BOOLEAN,
defaultValue: 0
},
is_catch_all_config: {
allowNull: false,
type: Sequelize.BOOLEAN,
defaultValue: 0
},
blockedAt: {
type: Sequelize.DATE
},
deletedAt: {
type: Sequelize.DATE
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
}, {
uniqueKeys: {
keyword_unique_for_bot_and_parent: {
customIndex: true,
fields: ['bot_id', 'parent_id', 'keyword', 'deletedAt']
}
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('Keywords');
}
};
It creates a foreign key but, both onUpdate and onDelete are set to RESTRICT
I went through their documentation but could not find something that works.
You should try to add that action in your Keywords model file where we can define association.
static associate(models) {
// define association here
Keywords.hasMany(models.Bots, {
foreignKey: 'id',
onUpdate: 'RESTRICT',
onDelete: 'RESTRICT'
});
};
Thanks

Sequelize Multi Inserting Data

Hi everybody =) It's my first time using sequelize with postgresql, and I have problem with multi inserting data with sequelize(node.js). We have some tables(see in pic)
Table Relations
1) Clients -> 1:M -> Contracts
2) Contracts -> 1:M -> Contracts_attaches
3) Rates -> 1:M -> Contracts_attaches
Clients Model
const Client = db.define('clients', {
id_clients: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true,
},
nclients: {
type: Sequelize.STRING
}
-some fields-
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
Rate Model
const Rate = db.define('rates', {
id_rates: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true
}
--fields--
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
})
Contract Model
const Contract = db.define('contracts', {
id_contracts: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true
},
--fields--
id_clients: {
type: Sequelize.INTEGER,
allowNull: false
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
})
Contract_attach Model
const Contract_attach = db.define('contract_attach', {
id: {
type: Sequelize.INTEGER,
allowNull: false,
autoIncrement: true,
primaryKey: true
},
contracts_id: {
type: Sequelize.INTEGER,
references:{
model:'contracts',
key:'id_contracts'
}
},
rate_id: {
type: Sequelize.INTEGER
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
},
})
Association config
Contract.belongsTo(Contract_attach, { foreignKey:'id_contracts', sourceKey:'contracts_id' });
Contract_attach.hasMany(Contract,{foreignKey:'id_contracts', sourceKey:'contracts_id'});
Contract_attach.hasMany(Rate,{foreignKey: 'id_rates', sourceKey: 'rate_id'});
Rate.belongsTo(Contract_attach, { foreignKey: 'rate_id', sourceKey: 'id_rates' });
Example Inserting Data
I try insert data like this code
Contract.create({'numcontract':22,'datereg':'2019-12-11','id_clients':5,Contract_attach:[{'rate_id':2,'rate_id':3}]},
{include: [Contract_attach]}).then(result => console.log(result));
or this code
Contract.create({'numcontract':22,'datereg':'2019-12-11','id_clients':5,Contract_attach:[{'ratename':'Small Buissness','ratename':'Small Buissness 10'}]},
{include: [Contract_attach]}).then(result => console.log(result));
When I try insert data with this code, sequelize inserting data just for Contract table, and ignoring insert to Contract_attach.
PS. Rate table have data, and we don't need insert data to the Rate table.
For some, it may and will be useful, but I solved this problem like this
Contr.create({'numcontract':22,'datereg':'2019-12-11','id_clients':5})
.then(function(contr){
contract_att.bulkCreate([{'contracts_id':contr.id_contracts, 'rate_id':2},{'contracts_id':contr.id_contracts,'rate_id':3}]);
});
If you have another solution, pls share ))
There are several issues here
you said Contract > 1:M > Contract_attach then you write Contract_attach.hasMany(Contract...etc. it should be the other way around Contract.hasMany(Contract_attach...etc same goes for rates
In diagram there is relation between Contract_attach and rates but the define you didn't define this reference
Its not clear that columns rate_id and contract_id are nullable or not. based on that we can define if Contract_attach can or can not be belong to 2 different tables.
I think that the database schema need to change or explain why its in this way

Sequelize – id as uuid – automatic creation with bulkInsert

I have a model with such init:
Group.init({
id: {
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
},
name: Sequelize.STRING,
});
I also have an associated migration file:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Groups', {
id: {
type: Sequelize.UUID,
primaryKey: true,
allowNull: false,
defaultValue: Sequelize.UUIDV4,
},
name: Sequelize.STRING,
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Groups');
},
};
I'm trying to bulkInsert inside the seeders while creating groups and I'm passing only a name property, expecting the DB to create uuids:
const groups = [{ name: 'group-1' }, { name: 'group-2' }];
return queryInterface.bulkInsert('Groups', groups, {
returning: true,
validate: true,
individualHooks: true,
});
},
Yet there is an error during this seed:
ERROR: null value in column "id" violates not-null constraint
How can I automatically generate uuids?
I faced a similar issue. In my case (on the migration file), I changed
defaultValue: Sequelize.UUIDV4,
to
defaultValue: Sequelize.literal('uuid_generate_v4()'),
PS: I was working on Postgres, so uuid modules needed to be enabled on the schema

Sequelize query singular instead of plural table name

I have an problem and I can't find anything that can solve it. I'm using sequelize and graphql to create an API in nodeJS. The database is using PostgresQL.
So I have two models: Simulation and Data. They are in two tables Simulations and Datas. The relation between them is one Simulation to many Datas.
The problem is this: when I make a query with Simulation (ex: Simulation.findAll()), it works correctly, querying "Simulations", but with Data, it queries on the "Data" table, not "Datas". What I really don't understand is that the code of my two models are almost the same.
Here is the model for Simulation:
module.exports = (sequelize, DataTypes) => {
const Simulation = sequelize.define('Simulation', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
});
Simulation.associate = function(models) {
Simulation.hasMany(models.Data, {
foreignKey: 'SimulationId',
})
};
return Simulation;
};
Here is the model for Data:
module.exports = (sequelize, DataTypes) => {
const Data = sequelize.define('Data', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER,
},
name: {
type: DataTypes.STRING,
allowNull: false
},
content: {
type: DataTypes.TEXT,
allowNull: false
},
SimulationId: {
allowNull: false,
type: DataTypes.INTEGER,
},
});
Data.associate = function(models) {
Data.belongsTo(models.Simulation, {
foreignKey: 'SimulationId',
targetKey: 'id',
allowNull: false,
onDelete: 'CASCADE'
});
};
return Data;
};
And here are the migration files:
Simulation
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Simulations', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Simulations');
}
};
Data
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Datas', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
type: Sequelize.STRING,
allowNull: false
},
content: {
type: Sequelize.TEXT,
allowNull: false
},
SimulationId: {
allowNull: false,
type: Sequelize.INTEGER,
onDelete: 'CASCADE',
references: {
model: 'Simulation',
key: 'id',
as: 'SimulationId',
},
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Datas');
}
};
Thanks for helping me :)
You can use freezeTableName option to set whatever the model name you want, sequelize will not make the model names plural.
Sequelize automatically makes the model names plural. Why not call the table "Data" It is actually a plural form of the word "Data", so maybe a better name for the table.

How can I make a composite unique constraint with foreign keys and regular keys in Sequelize?

We have two models, users and items. Under User.js
User = Model.define('User', {
id: {
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
},
});
And under Item.js
Item = Model.define('Item', {
id: {
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
},
});
Here is their association, a user can have many items.
User.hasMany(Items, {
foreignKey: {
allowNull: false,
name: 'itemId',
},
onUpdate: 'cascade',
onDelete: 'cascade',
});
Assume that each user may only have one of each type of item. How do I add a unique constraint for this? The following code does not work.
User.hasMany(Items, {
foreignKey: {
allowNull: false,
name: 'itemId',
unique: 'userItemUnique',
},
onUpdate: 'cascade',
onDelete: 'cascade',
});
Item = Model.define('Item', {
id: {
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
unique: 'userItemUnique',
},
});
You can use migrations for this.
Sequelize-cli provides a methods addConstraint and andIndex which can be used to achieve
From the docs
queryInterface.addConstraint('Users', ['email'],
{ type: 'unique', name: 'custom_unique_constraint_name'
});
If anyone is still following this, I solved this by manually defining the foreign keys in the model where the unique constraint is required (you can still use sequelize association such as .hasMany).
Regarding your own code, I think there might be a confusion when you ask for Assume that each user may only have one of each type of item since you are not defining what is an item type.
I've drafted something with my own understanding and taking into account my previous comment.
User = Model.define('User', {
id: {
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
allowNull: false,
validate: {
isUUID: 1,
},
},
});
Item = Model.define('Item', {
id: {
type: DataType.UUID,
defaultValue: DataType.UUIDV1,
primaryKey: true,
allowNull: false,
validate: {
isUUID: 1,
},
},
type: {
type: DataType.STRING,
unique: 'uniqueUserItemType' // see note 1
}
userId: {
type: DataType.UUID,
references: { // see note 2
model: User,
key: 'id',
},
unique: 'uniqueUserItemType',
}
});
User.hasMany(Item, {
foreignKey: {
allowNull: false,
name: 'itemId',
},
onUpdate: 'cascade',
onDelete: 'cascade',
});
Item.belongsTo(User);
I've also added a belongsTo association as recommended by Sequelize.
[1] More info on composite unique constraint here.
[2] More info on foreign key definition inside of model here.
In my case I did something like this based on Joel Barenco's answer.
const { Model, DataTypes } = require('sequelize');
const User = require('../models/user');
module.exports = function(sequelize){
class Algorithm extends Model {}
UserModel = User(sequelize);//#JA - Gets a defined version of user class
var AlgorithmFrame = Algorithm.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
user_Id: {
type: DataTypes.INTEGER,
references: {
model: UserModel,
key: 'id',
},
}
}, {
sequelize,
modelName: 'Algorithm',
indexes: [{ unique: true, fields: ['name','user_id'] }]
});
return AlgorithmFrame
};
The idea here is to manually create the foreign key, but you can define the unique indexes instead with indexes: [{ unique: true, fields: ['name','user_id'] }]
My tactic also shows how to define the model in a class as well. To call it you simply pass sequelize to it like this, where sequelize is the variable holding all your connection info etc...
const Algorithm = require('../models/algorithm');
const AlogorithmModel = Algorithm(sequelize);
then you can make sure it's created with
await AlogorithmModel.sync({ alter: true });
My user model file is this:
const { Model, DataTypes } = require('sequelize');
module.exports = function(sequelize){
class User extends Model {}
return User.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false
},
trading_system_key: {
type: DataTypes.STRING,
allowNull: false
},
}, {
sequelize,
modelName: 'User',
indexes: [{ unique: true, fields: ['trading_system_key'] }]
});
};

Resources