Creating a one to one association with sequelize nodejs and postgresql - node.js

I am currently working a project using NodeJS and postgresql with Sequelize as the ORM.
I have two tables; and address table and a user table. I want the address primary key to be a foreign key in the user table.
THIS is how I have defined the association.
Address.hasOne(User);
User.belongsTo(Address, {
foreignKey:{
type:Sequelize.IMTEGER,
name: "address_id",
allowNull: false,
},
});
This is the definition of my address table using sequelize;
exports default (sequelize, DataTypes) =>{
const Address = sequelize.define("address ",{
address_id:{
type: DataTypes.INTEGER,
autoIncrement:true,
primaryKey: true,
unique:true
},
address_name:{
type: DataTypes.INTEGER,
allowNull: false,
validate:{
notNull:{
msg: "address name required!"
}
}
});
return Address;
}
And this is the user table:
exports default (sequelize, DataTypes) =>{
const User = sequelize.define("user ",{
user_id:{
type: DataTypes.INTEGER,
autoIncrement:true,
primaryKey: true,
unique:true
},
name:{
type: DataTypes.STRING,
allowNull: false,
validate:{
notNull:{
msg: "Name required!"
}
}
});
return User;
}
But when I run the synchronization, all the other columns get created except for the address_id column I expect in the User table.
I need help!
Thank everyone in advance

At least you need to indicate the same value for foreignKey option in both associations:
Address.hasOne(User, { foreignKey: 'address_id' });
User.belongsTo(Address, , { foreignKey: 'address_id' });
And it's better to explicitly define address_id in User model:
address_id:{
type: DataTypes.INTEGER,
notNull: true
},

Related

Associations with Sequelize Node/Express.js

I got some trouble understanding how associations works with Sequelize. I am working on a project which have almost the same features that Reddit and therefore I am trying to associate the User table to the Post table as a 1:N associations.
User Model:
const { Sequelize, Model, DataTypes } = require ('sequelize');
const db = require('../config/db');
const Post = require('./Post')
class User extends Model{}
User.init({
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
username:{
type: DataTypes.STRING,
unique: true
},
email:{
type: DataTypes.STRING
},
password:{
type: DataTypes.STRING
},
isAdmin:{
type: DataTypes.BOOLEAN,
defaultValue: false
}
}, {sequelize: db, modelName:'User'}
);
User.hasMany(Post,{as: 'posts', foreignKey: 'id'});
User.sync();
module.exports = User;
Post Model:
const { Sequelize, Model, DataTypes } = require ('sequelize');
const db = require('../config/db');
const User = require('./User');
class Post extends Model{}
Post.init({
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
text:{
type: Sequelize.STRING
},
image:{
type: Sequelize.STRING
},
likes:{
type: Sequelize.INTEGER,
}
}, {sequelize: db, modelName:'Post'}
)
Post.sync();
module.exports = Post;
When I launch my app, I can see that it mention that post have the foreign key id but still I don't have hany column that link User to Post in my DB. What I am missing?
Executing (default): CREATE TABLE IF NOT EXISTS `Posts` (`id` INTEGER NOT NULL auto_increment , `text` VARCHAR(255), `image` VARCHAR(255), `likes` INTEGER, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`id`), **FOREIGN KEY (`id`)** REFERENCES `Users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB;
First, you need to indicate the correct value in the foreignKey option, it should be a field like user_id in Post model:
User.hasMany(Post,{as: 'posts', foreignKey: 'user_id'});
Second, you need to move association definitons and sync calls (and cross-refrences of models) from model modules outside. You need to register all models and only after that to define all their associations and the last action would be calling sync methods.
See the question and my answer here to get an idea how to do it.

Sequelize error with join table: DatabaseError [SequelizeDatabaseError]: column does not exist

I'm trying to run the following code block, for some reason the query tries to insert it into a column labeled "users->user_group"."userUuid", despite the fact that I have not reference the string literal userUuid once in the project (through search not in the code base), also check columns in pg-admin (using PostgreSQL), both columns in the user_group table are user_uuid and group_uuid, both columns are also validated and populated properly.
const result = await group.findAll({
include: user,
});
Postman body returns the following error
"hint": "Perhaps you meant to reference the column "users->user_group.user_uuid".",
I have 3 models user, group and user_group. The relations have been defined per documentation and countless other articles and videos.
user model
module.exports = (sequelize, DataTypes) => {
const user = sequelize.define(
"user",
{
uuid: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
unique: true,
},
username: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
},
{
freezeTableName: true,
}
);
user.associate = (models) => {
user.belongsToMany(models.group, {
// as: "userUuid",
through: models.user_group,
foreignKey: "user_uuid",
});
};
return user;
};
group model
module.exports = (sequelize, DataTypes) => {
const group = sequelize.define(
"group",
{
uuid: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
unique: true,
},
title: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
},
},
{
freezeTableName: true,
}
);
group.associate = (models) => {
group.belongsToMany(models.user, {
// as: "groupUuid",
through: models.user_group,
foreignKey: "group_uuid",
});
};
return group;
};
user_group model
module.exports = (sequelize, DataTypes) => {
const user_group = sequelize.define(
"user_group",
{
uuid: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
unique: true,
},
user_uuid: {
type: DataTypes.STRING,
allowNull: false,
references: {
model: "user",
key: "uuid",
},
},
group_uuid: {
type: DataTypes.STRING,
allowNull: false,
references: {
model: "group",
key: "uuid",
},
},
author: {
type: DataTypes.STRING,
unique: true,
allowNull: true,
},
},
{
freezeTableName: true,
}
);
user_group.associate = (models) => {
user_group.belongsTo(models.user, {
foreignKey: "user_uuid",
});
user_group.belongsTo(models.group, {
foreignKey: "group_uuid",
});
};
return user_group;
};
Any help is much apprecaited, thanks!
You should indicate otherKey option along with foreignKey in belongsToMany in order to indicate a foreign key column on the other model otherwise you will end up with a default name of an other key, see below:
The name of the foreign key in the join table (representing the target model) or an object representing the type definition for the other column (see Sequelize.define for syntax). When using an object, you can add a name property to set the name of the column. Defaults to the name of target + primary key of target (your case: user+uuid)
group.belongsToMany(models.user, {
// as: "groupUuid",
through: models.user_group,
foreignKey: "group_uuid",
otherKey: "user_uuid"
});
const result = await group.findAll({
include: {user},
});
you should to create like this. baecause you missing this {}.

How to create an object of a relationship in sequelize?

Hey I need to create a relationship in sequelize. I have the model and is well created in the database.
I'll show you my models but it's not very relevant.
Seller Model
const Sellers = db.define("sellers", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: Sequelize.STRING,
surname: Sequelize.STRING,
});
Sellers.hasMany(Clients);
module.exports = Sellers;
Client Model
const Client = db.define("clients", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: Sequelize.STRING,
creationDate: Sequelize.DATE,
client_type: Sequelize.STRING,
});
module.exports = Client;
What I want to do is simply make a relation between the client and seller. In the database a SellerId is added in the client table because of sequelize hasMany() method. What I want to do is just be able to pass the id to the ORM when creating a client so it makes the relationship automatically to the seller table.
Sequelize Documentation about this
Thank you for taking your time to read this. I hope you can help me! Have a great day.
First of all I'd prefer to define a foreign key column in a model and indicate it in associations explicitly. And of course you need to add another association from clients to sellers - belongsTo and call both of associations outside models to be able to reference them to each other.
Client model file:
const Client = db.define("clients", {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: Sequelize.STRING,
creationDate: Sequelize.DATE,
client_type: Sequelize.STRING,
sellerId: {
type: Sequelize.INTEGER,
allowNull: false // or true if this association is optional
},
});
some database.js file where you should register all associations:
....
Sellers.hasMany(Clients, { foreignKey: 'sellerId' });
Clients.belongsTo(Sellers, { foreignKey: 'sellerId' });
And then you can create a client indicating a seller's id:
const seller = await Seller.findOne({
where: {
name: 'Peter'
}
})
const newClient = await Client.create({
name: 'John',
sellerId: seller.id,
// other fields here
})

Persist constraint unique after destroy

I have a users table with the unique username. When I delete the users and recreate the same users the error appears:
Error: SQLITE_CONSTRAINT: UNIQUE constraint failed
It seems that unique count of the username is persistent after destroy. Is there a way to remove this constraint after deleting?
I have seen in the sequelize documentation that hooks exist but I don't quite understand how to apply it
UPDATE
const Sequelize = require('sequelize');
// Connection
const { sequelize } = require('../config/sequelize');
const UserSource = require('./UserSource');
const User = sequelize.define('user', {
user_id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
},
username: {
type: Sequelize.STRING(100),
unique: true,
},
name: {
type: Sequelize.STRING(100)
},
place_id: {
type: Sequelize.INTEGER,
allowNull: false,
},
}, {
paranoid: true,
timestamps: false,
});
User.hasMany(UserSource, { foreignKey: 'user_id', sourceKey: 'user_id'});
UserSource.belongsTo(User, { foreignKey: 'user_id', sourceKey: 'user_id'});
module.exports = User;
I've also tried paranoid: false and it still doesn't work

Unrecognized datatype in Sequelize Model

I am trying to create an attribute called "provider" in my postgresql model and make its data type an Object (see code below). However, I am getting the error Error: Unrecognized datatype for attribute "segment.provider".
I'm assuming this error is happening because I haven't specified what the data type of the "provider" attribute actually is (ie: type: DataTypes.OBJECT). To my knowledge, there's nothing in the Sequelize docs that demonstrates this ask of mine. Any and all help would be most appreciated. Thanks!
module.exports = (sequelize, DataTypes) => {
const Segment = sequelize.define(
'segment',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
provider: {
providerName: DataTypes.STRING,
externalId: DataTypes.STRING,
email: DataTypes.STRING,
privacyPolicy: DataTypes.STRING
}
},
{
freezeTableName: true,
tableName: 'segment'
}
);
return Segment;
}
Every field defined on a model(Table) is mapped into a column on the database.
That is what sequelize basically does.
Now, is there a field on a PostgreSQL database which is an object?
For what you are trying to do, you just need to use associations between tables.
Create a new model (Table) called provider:
And add the associations as follows in the example:
module.exports = (sequelize, DataTypes) => {
const Provider = sequelize.define(
'provider',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: DataTypes.STRING
},
email: {
type: DataTypes.STRING
},
privacyPolicy: {
type: DataTypes.STRING
}
},
{
freezeTableName: true,
tableName: 'provider'
}
);
// Apply the accosiation:
Provider.hasMany /* or has one */ (Segment, {foreignKey: 'provider_id'});
return Provider;
}
And in your Segment model add a foreign key and a reference to Provider
module.exports = (sequelize, DataTypes) => {
const Segment = sequelize.define(
'segment',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
provider_id: {
type: DataTypes.INTEGER,
references: {
model: 'provider',
key: 'id
}
}
},
{
freezeTableName: true,
tableName: 'segment'
}
);
// Apply the accosiation:
Segment.belongsTo(Provider, {foreignKey: 'id'});
return Segment;
}

Resources