HasOne and belongsTo relationships in the same model sequelize - javascript

I'm using sequelize along with nodejs and am having difficulties with a relationship.
I have 3 tables where (local, equipment, shed, area) where in one place I have 1 equipment, it is in a shed and belongs to an area.
The models look like this:
local:
import { Sequelize, DataTypes } from 'sequelize';
export default (sequelize, dataTypes) => {
const model = sequelize.define('local', {
id: {
type: dataTypes.STRING(200),
primaryKey: true,
allowNull: false,
required: true,
unique: true
},
name: {
type: dataTypes.STRING(200),
allowNull: false,
required: true
},
idEquipment: {
type: dataTypes.STRING(200),
allowNull: false,
required: true
},
idShed: {
type: dataTypes.STRING(200),
allowNull: false,
required: true
},
idArea: {
type: dataTypes.STRING(200),
allowNull: false,
required: true
},
situation: {
type: dataTypes.BOOLEAN,
allowNull: false,
required: true,
defaultValue: true
},
capacity: {
type: dataTypes.FLOAT,
allowNull: false,
required: true
},
posX: {
type: dataTypes.STRING,
allowNull: false,
required: true
},
posY: {
type: dataTypes.STRING,
allowNull: false,
required: true
},
posZ: {
type: dataTypes.STRING,
allowNull: false,
required: true
},
status: {
type: dataTypes.BOOLEAN,
allowNull: true,
defaultValue: true
}
}).schema('public');
model.associate = (models) => {
model.belongsTo(models.area, {
foreignKey: 'idArea'
});
model.belongsTo(models.equipment, {
foreignKey: 'idEquipment'
});
// model.belongsTo(models.shed, {
// foreignKey: 'idShed'
// });
};
return model;
};[]
equipment:
import { Sequelize, DataTypes } from 'sequelize';
export default (sequelize, dataTypes) => {
const model = sequelize.define('equipment', {
id: {
type: dataTypes.STRING(200),
primaryKey: true,
allowNull: false,
unique: true,
required: true
},
description: {
type: dataTypes.STRING(200),
allowNull: false,
required: true
},
idArea: {
type: dataTypes.STRING(200),
allowNull: true,
required: false
},
idHangar: {
type: dataTypes.STRING(200),
allowNull: true,
required: false
},
idControlPlan: {
type: dataTypes.STRING(200),
allowNull: true,
required: false
},
dateControlPlan: {
type: dataTypes.DATE,
allowNull: true,
required: false
},
idUserControlPlan: {
type: dataTypes.STRING(200),
allowNull: true,
required: false
},
status: {
type: dataTypes.BOOLEAN,
allowNull: true,
defaultValue: true
}
}).schema('public');
model.associate = (models) => {
model.hasOne(models.local, {
foreignKey: 'idEquipment'
});
};
return model;
};
shed:
import { Sequelize, DataTypes } from 'sequelize';
export default (sequelize, dataTypes) => {
const model = sequelize.define('shed', {
id: {
type: dataTypes.STRING(200),
primaryKey: true,
allowNull: false,
unique: true,
required: true
},
idArea: {
type: dataTypes.STRING(200),
allowNull: false,
required: true
},
description: {
type: dataTypes.STRING(200),
allowNull: false,
required: true
},
status: {
type: dataTypes.BOOLEAN,
allowNull: true,
defaultValue: true
}
}).schema('public');
model.associate = (models) => {
// model.hasOne(models.local, {
// foreignKey: 'idShed'
// });
model.belongsTo(models.area, {
foreignKey: 'idArea'
});
};
return model;
};
area:
import { Sequelize, DataTypes } from 'sequelize';
export default (sequelize, dataTypes) => {
const model = sequelize.define('area', {
id: {
type: dataTypes.STRING(200),
primaryKey: true,
allowNull: false,
unique: true,
required: true
},
description: {
type: dataTypes.STRING,
unique: true,
allowNull: false,
required: true
},
status: {
type: dataTypes.BOOLEAN,
allowNull: true,
defaultValue: true
}
}).schema('public');
model.associate = (models) => {
model.belongsToMany(models.company, {
through: 'companyArea',
foreignKeyConstraint: true,
foreignKey: 'idArea'
});
model.hasOne(models.shed, {
foreignKey: 'idArea'
});
model.hasOne(models.local, {
foreignKey: 'idArea'
});
};
return model;
};
When I add the shed relationship, it informs me that there is no relationship, when shooting everything will normally:
[SQL Error] SequelizeDatabaseError: relation "public.sheds" does not exist EXIT
[SQL Error] relation "public.sheds" does not exist EXIT
I am using postgres database.
Where could that be the mistake, would it be a writing error? Or a template can not have a belongsTo and hasOne relationship at the same time?

Related

nodejs - Sequelize association between labors model and room capacity

I have to models labor and room_capacity, every may have different capacity 4,5,8,10
second model is rooms
I need to do association between rooms in both models to get room capacity while findAll()
the association and model.findAll required.
the first model :
module.exports = (sequelize, DataTypes) => {
const haramain = sequelize.define("haramain", {
emp_no: {
type: DataTypes.BIGINT,
allowNull: false,
},
name: {
type: DataTypes.STRING,
allowNull: false
},
zoon_no: {
type: DataTypes.INTEGER,
allowNull: false
},
room_no: {
type: DataTypes.INTEGER,
allowNull: false
},
room: {
type:DataTypes.STRING,
get() {
function zeroPad(num, places) {
let zero = places - num.toLocaleString('EG').length + 1;
return Array(+(zero > 0 && zero)).join("0") + num;
}
const room = this.getDataValue('room_no')
const zoon = this.getDataValue('zoon_no')
return `Z${zoon}-${zeroPad(room,3)}`
}
},
profession: {
type: DataTypes.STRING,
allowNull: true
},
nationality: {
type: DataTypes.STRING,
allowNull: false
},
project: {
type: DataTypes.STRING,
allowNull: false
},
iqama_no: {
type: DataTypes.BIGINT,
allowNull: false
},
passport_no: {
type: DataTypes.STRING,
allowNull: true
},
in_date: {
type: DataTypes.DATEONLY,
allowNull: false,
},
emp_photo: {
type: DataTypes.BLOB,
allowNull: true
},
iqama_photo: {
type: DataTypes.BLOB,
allowNull: true
},
in_reason: {
type: DataTypes.STRING,
allowNull: false
},
out_date: {
type: DataTypes.DATEONLY,
allowNull: true
},
});
return haramain;
};
second model:
module.exports = (sequelize, DataTypes) => {
const haramainrooms = sequelize.define("haramainrooms", {
room: {
type: DataTypes.STRING,
allowNull: false,
},
capacity: {
type: DataTypes.INTEGER,
allowNull: true
}
});
return haramainrooms;
};
I have to models labor and room_capacity, every may have different capacity 4,5,8,10
second model is rooms
I need to do association between rooms in both models to get room capacity while findAll()
the association and model.findAll required.

How to do a query in Sequelize?

I've an existing Postgres database. Throught sequelize-auto, I generated the models for the existing database. For example, let's look at the tc_devices table (tc_devices.js):
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('tc_devices', {
id: {
autoIncrement: true,
autoIncrementIdentity: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
name: {
type: DataTypes.STRING(128),
allowNull: false
},
uniqueid: {
type: DataTypes.STRING(128),
allowNull: false,
unique: "tc_devices_uniqueid_key"
},
lastupdate: {
type: DataTypes.DATE,
allowNull: true
},
positionid: {
type: DataTypes.INTEGER,
allowNull: true
},
groupid: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: 'tc_groups',
key: 'id'
}
},
attributes: {
type: DataTypes.STRING(4000),
allowNull: true
},
phone: {
type: DataTypes.STRING(128),
allowNull: true
},
model: {
type: DataTypes.STRING(128),
allowNull: true
},
contact: {
type: DataTypes.STRING(512),
allowNull: true
},
category: {
type: DataTypes.STRING(128),
allowNull: true
},
disabled: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: false
}
}, {
sequelize,
tableName: 'tc_devices',
schema: 'public',
timestamps: false,
indexes: [
{
name: "tc_devices_pkey",
unique: true,
fields: [
{ name: "id" },
]
},
{
name: "tc_devices_uniqueid_key",
unique: true,
fields: [
{ name: "uniqueid" },
]
},
]
});
};
In database.js, I connect to the database:
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize(database, user, password, {
host,
port,
dialect: 'postgres',
logging: false
})
async function db_connection(){
try{
await sequelize.authenticate();
console.log('Connection has been estabilished successfully.');
}catch{
console.log('Unable to connect to the database.');
}
}
db_connection()
How can I do a simple query on the tc_devices table? what should I import in database.js? in tc_devices I export function(sequelize, DataTypes)... but I can't understand how to do a query in database.js with this function...could you help me? thank you so much.
You need to register all models and their associations before executing the first query with these models. Look at my answer here.
As soon as you do it you can execute queries like this:
// assuming db already stores all model definitions
const allRecords = await db.tcDevices.findAll({})

How to create a sequelize composite constraint with a local table column and a column present in the foreign key table

I'm using Sequelize and PostgreSQL to create a node app and get stuck in this problem. I have three models in sequelize which are:
BoxTemplate
BoxTemplateWorkspace
Workspace
The model BoxTemplateWorkspace is a Many to many association that links many BoxTemplate to many Workspace. What I'm trying to do is to create a composite unique constraint inside the BoxTemplate model, interconnecting a column Title in my BoxTemplate with a column WorkspaceCode which is inside my BoxTemplateWorkspace.
I already know how to create a composite unique constraint with normal columns and with FK columns that reside in the same table/model. But I'm not able to get through this.
Bellow my code to get a better understanding
BoxTemplate.js
var boxTemplate = sequelize.define('BoxTemplate', {
ID: {
type: DataTypes.UUIDV4,
defaultValue: sequelize.literal('gen_random_uuid()'),
allowNull: false,
primaryKey: true,
unique: title_WorkspaceCode_unique
},
Title: {
type: DataTypes.STRING(150),
allowNull: false,
unique: true
},
//... more columns
}, {
indexes: [{
unique: 'title_WorkspaceCode_unique',
fields: ['Title', /*here should fit the WorkspaceCode present in BoxTemplateWorkspace*/]
}],
createdAt: 'CreatedDate',
updatedAt: 'LastUpdate',
timestamps: true,
underscored: false,
freezeTableName: true,
});
boxTemplate.associate = models => {
// model that makes a many to many relationship
boxTemplate.hasMany(models.BoxTemplateWorkspace, {foreignKey: 'BoxTemplateCode'});
}
return boxTemplate;
};
BoxTemplateWorkspace
var boxTemplateWorkspace = sequelize.define('BoxTemplateWorkspace', {
ID: {
type: DataTypes.UUIDV4,
defaultValue: sequelize.literal('gen_random_uuid()'),
allowNull: false,
primaryKey: true,
unique: true
},
IsActive: {
type: DataTypes.BOOLEAN,
defaultValue: true,
allowNull: false
},
InactivatedDate: {
type: DataTypes.DATE,
},
},{
timestamps: false,
underscored: false,
freezeTableName: true
});
boxTemplateWorkspace.associate = models => {
boxTemplateWorkspace.belongsTo(models.BoxTemplate, { foreignKey: 'BoxTemplateCode' });
// column that I want to use as a composite unique constraint
boxTemplateWorkspace.belongsTo(models.Workspace, { foreignKey: 'WorkspaceCode' });
boxTemplateWorkspace.belongsTo(models.UserSK, { foreignKey: 'InactivatedByUserCode' });
}
return boxTemplateWorkspace;
};
As suggested here the UserSK and Workspace Models
UserSK.js
var userSk = sequelize.define('UserSK', {
ID: {
type: DataTypes.UUIDV4,
defaultValue: sequelize.literal('gen_random_uuid()'),
allowNull: false,
primaryKey: true,
unique: true
},
Email: {
type: DataTypes.STRING(320),
allowNull: false,
unique: true
},
UserName: {
type: DataTypes.STRING(150),
allowNull: false,
unique: true
},
}, {
createdAt: 'CreatedDate',
updatedAt: 'LastUpdate',
timestamps: true,
underscored: false,
freezeTableName: true
});
userSk.associate = models => {
userSk.hasMany(models.BoxTemplate, {foreignKey: 'CreatedByUserCode'});
userSk.hasMany(models.BoxTemplate, {foreignKey: 'UpdatedByUserCode'});
}
return userSk;
Workspace.js
var workspace = sequelize.define('Workspace', {
ID: {
type: DataTypes.UUIDV4,
defaultValue: sequelize.literal('gen_random_uuid()'),
allowNull: false,
primaryKey: true,
unique: true
},
InvitedDate: {
type: 'TIMESTAMP',
defaultValue: sequelize.literal('CURRENT_TIMESTAMP'),
allowNull: true
},
WorkspaceName: {
type: DataTypes.STRING(100),
allowNull: true
}
}, {
timestamps: false,
underscored: false,
freezeTableName: true
});
workspace.associate = models => {
workspace.hasMany(models.BoxTemplateWorkspace, {foreignKey: 'WorkspaceCode'});
}
return workspace;
};

Sequelize - foreign key on create include returns null

The foreign key returns null when inserted using create include, but the rest of data is saved from the passed object.
Here is my transaction model:
module.exports = (sequelize, DataTypes) => {
const Transaction = sequelize.define('transactions', {
id: {
type: DataTypes.INTEGER,
allowNull: true,
primaryKey: true
},
receiptNumber: {
type: DataTypes.TEXT,
allowNull: true
},
supCustID: {
type: DataTypes.INTEGER,
allowNull: true
},
userID: {
type: DataTypes.INTEGER,
allowNull: true
},
type: {
type: DataTypes.TEXT,
allowNull: true
},
status: {
type: DataTypes.INTEGER,
allowNull: true
},
remarks: {
type: DataTypes.TEXT,
allowNull: true
},
createdAt: {
type: 'TIMESTAMP',
defaultValue: sequelize.literal('CURRENT_TIMESTAMP'),
allowNull: false
},
updatedAt: {
type: 'TIMESTAMP',
defaultValue: sequelize.literal('CURRENT_TIMESTAMP'),
allowNull: false
}
}, {
tableName: 'transactions'
});
Transaction.associate = models => {
Transaction.Order = Transaction.hasMany(models.Order, {
as: 'Orders',
foreignKey: 'transaction_id'
})
Transaction.SupCust = Transaction.belongsTo(models.SupCust, {
as: 'SupCust',
foreginKey: 'supCustID'
})
Transaction.User = Transaction.belongsTo(models.User, {
as: 'User',
foreginKey: 'userID'
})
}
return Transaction;
};
Orders Model:
/* jshint indent: 1 */
module.exports = (sequelize, DataTypes) => {
const Order = sequelize.define('orders', {
id: {
type: DataTypes.INTEGER,
allowNull: true,
primaryKey: true
},
transaction_id: {
type: DataTypes.INTEGER,
allowNull: true
},
itemID: {
type: DataTypes.TEXT,
allowNull: true
},
qty: {
type: DataTypes.INTEGER,
allowNull: true
},
itemCost: {
type: DataTypes.REAL,
allowNull: true
},
discount: {
type: DataTypes.REAL,
allowNull: true
},
totalAmount: {
type: DataTypes.REAL,
allowNull: true
}
}, {
tableName: 'orders',
timestamps: false,
hooks: {
afterValidate: (Order) => {
console.log(Order)
},
}
});
Order.associate = models => {
Order.belongsTo(models.Transaction, {
as: 'Transactions',
foreignKey: 'transaction_id'
})
Order.belongsTo(models.ItemList, {
as: 'Items',
foreignKey: 'itemID'
})
}
return Order;
};
Code to execute insert data:
return await models.Transaction
.findOne({ where: { id: values.id || -1 } })
.then(async function (obj) {
if(obj) { // update
return await obj.update(values, {individualHooks: true});
}
else { // insert
const {id, ...payload} = values
return await models.Transaction.create(payload, {
include: [{
association: models.Transaction.Order
}],
});
}
})
Results from console:
Executing (default): INSERT INTO `transactions` (`id`,`receiptNumber`,`supCustID`,`userID`,`type`,`createdAt`,`updatedAt`) VALUES ($1,$2,$3,$4,$5,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP);
Executing (default): INSERT INTO `orders` (`id`,`transaction_id`,`itemID`,`qty`,`itemCost`) VALUES ($1,$2,$3,$4,$5);
Console log from hooks on orders model:
dataValues:
{ id: null,
itemID: 1008,
itemCost: '2',
qty: '1',
transaction_id: null },
Why is this always null? what am i missing something?
Solved this by adding autoincrement property on my transaction model.
id: {
type: DataTypes.INTEGER,
allowNull: true,
primaryKey: true,
autoIncrement: true
}

Sequelize: belongsToMany and cascade deleting

Good day. I have 3 tables:
People: id, name
Places: id, name
PeoplePlaces: id, person_id, place_id
And i have models for this tables:
function Person(Sequelize, sequelize) {
return sequelize.define('people', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING,
allowNull: false
},
birthdate: {
type: Sequelize.DATE,
allowNull: false
}
}, {
timestamps: false
});
}
function Place(Sequelize, sequelize) {
return sequelize.define('places', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
allowNull: false
}
}, {
timestamps: false
});
}
function PersonPlace(Sequelize, sequelize) {
return sequelize.define('peopleplaces', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
}
}, {
timestamps: false
});
}
So, e.g. i want to delete person with id = 1:
sequelize.people.destroy({ where: { personId: pId } })
But i have an error on deleting, that says to me that table PersonPlaces contains FK to Person and it cannot be deleted.
I try to use onDelete: 'cascade': People.belongsToMany(Places, { through: PeoplePlaces, onDelete: 'cascade' });
But without good result.
So, how i can delete one person from People that have FK on it from PeoplePlaces?

Categories

Resources