How to create an object of a relationship in sequelize? - node.js

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
})

Related

Creating a one to one association with sequelize nodejs and postgresql

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
},

Sequelize Associate: User is not associated to Appointments

Basically I have a user model and appointment model. The two models are linked with a one-to-many relationship. The Appointment table has two columns that are associated with the user model. When ever I try to include the properties of the user table in appointment, I get the above error.
These are my model designs
Appointment Model
export default ({
sequelize
}:{
sequelize: Sequelize
}) => {
const Appointments: ModelDefined<AppointmentsAttribute, AppointmentsCreationAttributes> = sequelize.define('Appointments', {
appointmentId: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
client: {
type: DataTypes.STRING,
allowNull: false,
references: {
model: 'Users',
key: 'uid'
}
},
serviceProvider: {
type: DataTypes.STRING,
allowNull: false,
references: {
model: 'Users',
key: 'uid'
}
},
})
return Appointments
}
User Model
export default ({
sequelize
}: {
sequelize: Sequelize
}) => {
const User: ModelDefined<UserAttribute, UserCreationAttributes> = sequelize.define('User', {
uid: {
type: DataTypes.STRING,
allowNull: false,
unique:true,
primaryKey: true
},
firstname: {
type: DataTypes.STRING,
allowNull: false,
},
lastname: {
type: DataTypes.STRING,
allowNull: false,
},
}
})
return User
}
I have associated the user and appointment models with
Users.hasMany(Appointments);
The code that I am trying to use to fetch the appointment data and include the corresponding user value is
db.appointment.findAll({
where: {
client: this.uid
},
include: 'Users'
})
Sequelize always use associations for models whose association method was called. i.e. if you call Model1.hasMany(Model2) then you can execute queries like:
Model1.findAll({
include: [{
model: Model2
}]
}
and NOT vice versa like this:
Model2.findAll({
include: [{
model: Model1
}]
}
If you wish to request appointment with users as an associated model then you need to add a reversed association from Appointments to Users like this:
Users.hasMany(Appointments);
Appointments.belongsTo(Users);

How to Perform Multiple Inner Joins in Sequelize Postgresql

Am newbie to RDBMS and Sequelize as well wanted to explore more in those now am struck up with JOINS. I don't know how to perform JOINS via SEQUELIZE. I have 3 tables USERS,ORDERS,PRODUCTS ORDERS table contains USERS,PRODUCTS primary key as its foreign key. Am attaching my model code below
User Model
const Sequelize = require('sequelize');
const sequelize = require('../config');
let Users = sequelize.define('users', {
id : {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
username: {
type: Sequelize.STRING,
},
password: {
type: Sequelize.STRING
}
});
module.exports = Users;
Products Model
const Sequelize = require('sequelize');
const sequelize = require('../config');
let products=sequelize.define('products', {
id : {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
category : {
type: Sequelize.STRING,
allowNull: false
},
name : {
type: Sequelize.STRING,
allowNull: false
},
price: {
type: Sequelize.INTEGER,
allowNull: false
}
});
module.exports= products;
Orders Model
const Sequelize = require('sequelize');
const sequelize = require('../config');
let users=require('./user');
let products=require('./product');
let orders=sequelize.define('orders', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
user_id: {
type: Sequelize.INTEGER,
references: {
model: 'users',
key: 'id'
}
},
product_id: {
type: Sequelize.INTEGER,
references: {
model: 'products',
key: 'id'
}
},
price: {
type: Sequelize.INTEGER,
allowNull: false
}
});
module.exports= orders;
I want this following raw query to be performed via SEQUELIZE
SELECT * FROM ((orders INNER JOIN users ON users.id=orders.user_id) INNER JOIN products ON products.id=orders.product_id);
I have looked at the documentation but i couldn't figure out how to do it. ANy help is appreciated. Thanks
First thing you need to do is set up your Associations.
So lets break this up in to parts. We know that your ORDERS table contains the id for a USER and a PRODUCT. So this is how you would set up your associations for these tables.
I am assuming that a user has many orders. We make the associations in both directions.
User.hasMany(Orders, {foreignKey: 'user_id'});
Order.belongsTo(User, {foreignKey: 'user_id'});
You have the model correctly defined it seems.
Now in order to do a join, after setting up the associations, we want to set up a query to do joins for tables. Now keep in mind this would be done in your controller.
// Make sure you import your models up here to use below
export function getRequestsByWeek(req, res) {
return order.findAll({
include: [
{model: users, attributes: []}, // nothing in attributes here in order to not import columns from users
{model: products} // nothing in attributes here in order to not import columns from products
],
attributes: ['id'], //in quotes specify what columns you want, otherwise you will pull them all
// Otherwise remove attributes above this line to import everything.
})
.then(respondWithResult(res))
.catch(handleError(res));
}
let users=require('./user');
let products=require('./product');
export function getOrders(req, res) {
return order.findAndCountAll({
include: [
{model: users, required: true}, // true for INNER JOIN
{model: products, required: false} // false for LEFT OUTER JOIN
],
them all
})
}

Sequelize CLI how to create migrations from models?

I have two models with relations one to many.
I don't understand how to create migration files. Does each model have its own migration file or one migration file can create several tables from models and relations between them (for example as in rails migrations)?
I had a look at many examples including Sequelize docs, and there are primitive examples of models creating and its migration.
//User model
module.exports = function (sequelize, Sequelize) {
var User = sequelize.define('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
password: {
type: Sequelize.STRING,
allowNull: false,
},
});
return User;
}
//Order model
module.exports = function (sequelize, Sequelize) {
var Order = sequelize.define('orders', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
price: {
type: Sequelize.INTEGER,
allowNull: false,
},
totalPrice: {
type: Sequelize.INTEGER,
allowNull: false,
},
});
return Order;
}
//db.js
//Relations
db.orders.belongsTo(db.users);
db.users.hasMany(db.orders);
Addition
I create migration for two models:
module.exports = {
up: function (queryInterface, Sequelize, done) {
return [
queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
email: {
type: Sequelize.STRING,
allowNull: false,
unique: true,
},
password: {
type: Sequelize.STRING,
allowNull: false,
},
}),
queryInterface.createTable('orders', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
price: {
type: Sequelize.INTEGER,
allowNull: false,
},
totalPrice: {
type: Sequelize.INTEGER,
allowNull: false,
},
userId: {
type: Sequelize.INTEGER,
references: {
model: 'users',
key: 'id'
},
onUpdate: 'CASCADE',
onDelete: 'CASCADE'
}
}),
done()
]
},
down: function (queryInterface, Sequelize, done) {
return [
queryInterface.dropTable('users'),
queryInterface.dropTable('orders'),
done()
]
}
};
Do I need to add into my migration file class methods for my models?
//for Order
classMethods: {
associate: function(models) {
Model.belongsTo(models.users, (as: 'users'));
}
}
//for User
classMethods: {
associate: function(models) {
Model.hasMany(models.orders, (as: 'orders'));
}
}
//Addition 2
In order to create new migration file you need to call sequelize migration:create, which creates new file in /migrations directory (that is default migrations directory, can be different). In the migration file you can use bunch of functions in order to create tables, update them or specified table columns etc. If you want you can create all your database tables within single migration file. There is no straight connection between your models and migration files - they are independent on each other. The same concerns relations between models/table. You need to specify that given column in given table references other table.
// example column definition inside migration file
// creates a foreign key referencing table 'users'
userId: {
type: Sequelize.INTEGER,
references: {
model: 'users',
key: 'id'
},
onDelete: 'CASCADE'
}
You just need to remember about consistency between fields definition in Model and field/column definitions in the migration file corresponding to specified model/table.
You can also use command sequelize model:create, which, at the same time, creates a file used for defining a Sequelize model, as well as migration file responsible for creating a table corresponding to this model.
In order to show all possible sequelize-cli commands simply run sequelize help.
EDIT
The class methods like associate must be present only in the Model definition files, not in the migration files.
EDIT 2
The functions used in migration files like createTable are asynchronous, so you cannot simply run them in order just like you did it in your migration file. You can chain them via .then() method or return them as an array like
return [queryInterface.createTable(...), queryInterface.createTable(...)];

Use Model collection as data-type in sequelize

Background:
This is for a product database prototype, each product can have multiple related products, and each relationship has a type, e.g. 'Accessory', 'Spare Part', 'Related to', 'Similar to', etc.
Technology
We are using sequelize js on node to define the model.
Model Snippet:
sequelize.define('Product', {
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
name: { type: DataTypes.STRING, allowNull: false, comment: 'product name'}
...
});
sequelize.define('ProductRelationType', {
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
name: { type: DataTypes.STRING, allowNull: false, comment: 'relationship type description' }
});
sequelize.sync({force: false}).then( function() {
...
});
Question
Is it possible to use models themselves as datatypes in Sequelize, to establish a collection in another table, for example:
sequelize.define('ProductRelation', {
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
relatedProduct: { type: Product } //reference to product model
});
and followed by:
Product.hasMany(ProductRelation, { as: 'relatedProducts' });
ProductRelation.hasOne(ProductRelationType, { as: 'RelationType' } );
alternatively, exclude the ProductRelation table definition, and use:
db.Product.hasMany(db.Product, { through: 'RelatedProduct' } );
db.RelatedProduct.hasMany(db.Product, { through: 'RelatedProduct' } );
Note: These are concept examples, they do not work.
Any suggestions, or alternative modeling approaches are appreciated.
Thank you
It appears, what you want is simply establishing an n:m relationship from Product to Product.
The only way to get there is by establishing a link- (or "through-") table. You can either do it manually or let Sequelize do it automatically using belongsToMany:
var RelatedProducts = sequelize.define('RelatedProducts', {
// other columns here
});
Product.belongsToMany(Product, { through: RelatedProducts, foreignKey: 'relatedProductId' });
Product.belongsToMany(Product, { through: RelatedProducts });

Resources