Why does associating belongsTo in Sequelize give me this error? - node.js

I'm stuck with this problem for quite some time now and I don't know what's wrong with my code I'm trying to associate one table to another but only half of it works any help would be greatly appreciated.
models/companies.js
const DataTypes = require('sequelize');
const sequelize = require('../config/database');
const Users = require('./users');
const Companies = sequelize.define(
'companies',
{
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
name: {
type: DataTypes.STRING(50),
unique: true,
allowNull: false
},
image_url: {
type: DataTypes.STRING(100),
unique: true
},
created_at: {
allowNull: true,
type: DataTypes.DATE,
defaultValue: Date.now()
},
updated_at: {
allowNull: true,
type: DataTypes.DATE,
defaultValue: Date.now()
}
},
{
//Rewrite default behavior of sequelize
timestamps: false,
paranoid: true,
underscored: true
}
);
Companies.hasMany(Users);
Users.belongsTo(Companies);
Companies.sync();
module.exports = Companies;
models/users.js
const DataTypes = require('sequelize');
const sequelize = require('../config/database');
const Users = sequelize.define(
'users',
{
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
name: {
type: DataTypes.STRING(40),
allowNull: false
},
email: {
type: DataTypes.STRING(60),
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING(60)
},
role: {
type: DataTypes.STRING(40),
allowNull: false
},
image_url: {
type: DataTypes.STRING(100),
unique: true
},
batch: {
type: DataTypes.STRING(3)
},
major: {
type: DataTypes.STRING(10)
},
company_id: {
type: DataTypes.INTEGER,
allowNull: false
},
created_at: {
allowNull: true,
type: DataTypes.DATE,
defaultValue: Date.now()
},
updated_at: {
allowNull: true,
type: DataTypes.DATE,
defaultValue: Date.now()
}
},
{
//Rewrite default behavior of sequelize
timestamps: false,
paranoid: true,
underscored: true
}
);
Users.sync();
module.exports = Users;
Then after I try to run this code below
const Companies = require('./database/models/companies');
const Users = require('./database/models/Users');
//Relation 1: Company and Users
Companies.findAll({ include: [ Users ] }).then((res) => console.log(res));
Users.findAll({ include: [ Companies ] }).then((res) => console.log(res));
it gives me this error:
(node:4893) UnhandledPromiseRejectionWarning: SequelizeEagerLoadingError: companies is not associated to users!
I've tried a couple of solutions online but it didn't help in this case.

BelongsTo means one to one relationship while a company may have multiple users (meaning, calling BelongsTo after hasMany collide!).
For more: https://sequelize.org/master/manual/assocs.html

Related

How to resolve "Error: belongsTo called with something that's not a subclass of Sequelize.Model "?

So I've been trying to build a medium-clone for a project and therefore, I need to make a 1 : N relation for my "User" and "Article" Tables. But when I add the association Article.belongsTo(User); , I receive an error stating Error: Article.belongsTo called with something that's not a subclass of Sequelize.Model , and any kind of help would be highly appreciated.
Here's my code :
Article.js
const {Sequelize, DataTypes} = require('sequelize');
const db = require('../../config/Database');
const User = require('../User/User');
const Article = db.define('Article', {
slug : {
type: DataTypes.STRING(30),
allowNull: false,
primaryKey: true,
unique: true
},
title : {
type: DataTypes.STRING(50),
allowNull: false
},
description : {
type: DataTypes.STRING(100)
},
body : {
type: DataTypes.STRING
},
createdAt : {
allowNull: false,
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
updatedAt : {
allowNull: false,
type: DataTypes.DATE,
defaultValue: DataTypes.NOW
},
favorited : {
type : DataTypes.BOOLEAN,
defaultValue: 0
},
favoritesCount : {
type : DataTypes.INTEGER,
defaultValue : 0
}
},{
freezeTableName: true
})
Article.belongsTo(User);
module.exports = Article;
User.js
const {Sequelize,DataTypes} = require('sequelize');
const db = require('../../config/Database');
const Article = require('../Article/Article');
const User = db.define('User', {
email: {
type: DataTypes.STRING,
allowNull: false,
primaryKey: true,
unique: true
},
username: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
password: {
type: DataTypes.STRING,
allowNull: false
},
bio: {
type: DataTypes.STRING(100),
allowNull: true
},
image: {
type: DataTypes.STRING,
allowNull: true
},
token: {
type: DataTypes.STRING
}
},{
freezeTableName: true
})
User.hasMany(Article);
module.exports = User;

How can I set up modal database postgresSQL

I am using postgres for my database and I am trying to create a rule for each team
Here is my following code in my database:
module.exports = (sequelize, DataTypes) => {
const Team = sequelize.define(
"Team",
{
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
allowNull: false,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
type: DataTypes.STRING,
mission: DataTypes.STRING,
agreement: DataTypes.STRING,
},
{
tableName: "Teams",
timestamps: true,
indexes: [{ unique: false, fields: ["id", "title"] }],
}
);
So the agreement data type is my rules. Do I need to change it to array and create 4 rules in modal or is there anyways I can do it with string?

sequelize association N:M Table and 1:N Table

I am using sequelize, mysql for node.js!
Have a question and post it.
First, to create a review table with N: M relationship between user table and store table!
Please refer to the ReviewImage Table, which is a 1: N relationship with the Review Table.
For synchronization, please refer to the Review Table and ReviewImage Table.
I don't know what the problem is even if I browse the sequelize API documentation!
Have you ever done the wrong database design?
Should I design a review image table?
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(
config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.User = require('./UserModel')(sequelize, Sequelize);
db.Store = require('./StoreModel')(sequelize, Sequelize);
db.Review = require('./reviewModel')(sequelize, Sequelize);
db.ImageReview = require('./imageReviewModel')(sequelize, Sequelize);
/** N:M User : Store (Review) */
db.User.belongsToMany(db.Store, { through: db.Review});
db.Store.belongsToMany(db.User, { through: db.Review});
/** 1:N review : imageReview */
db.Review.hasMany(db.ImageReview);
db.ImageReview.belongsTo(db.Review);
module.exports = db;
// userModel.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('User',{
userPlatformType:{
type: DataTypes.STRING(50),
},
userNickname:{
type: DataTypes.STRING(50),
allowNull: false,
unique : true,
},
customerEmail: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
userPassword:{
type: DataTypes.STRING(200),
allowNull: false,
},
salt:{
type: DataTypes.STRING(200),
},
userPhoneNumber:{
type: DataTypes.STRING(45),
},
userDateOfBirth:{
type: DataTypes.DATEONLY,
},
userWeddingDay:{
type: DataTypes.DATEONLY,
},
userProfile: {
type: DataTypes.STRING(200),
allowNull: true,
},
}, {
freezeTableName: true,
});
};
// storeModel.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('Store',{
storeName:{
type: DataTypes.STRING(50),
},
storeCategory: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true,
},
storeAddress:{
type: DataTypes.STRING(150),
allowNull: false,
unique : true,
},
storeLatitude:{
type: DataTypes.STRING(45),
},
storeLongtitude:{
type: DataTypes.STRING(45),
},
storeCondition: {
type: DataTypes.STRING(200),
allowNull: false,
},
storePhoneNumber:{
type: DataTypes.STRING(200),
allowNull: false,
},
storeProfile:{
type: DataTypes.STRING(200),
},
storeWifi:{
type: DataTypes.STRING(45),
},
storePost:{
type: DataTypes.STRING(100),
},
storeItem:{
type: DataTypes.STRING(100),
},
storeIntro:{
type: DataTypes.STRING(100),
},
storeLike: {
type: DataTypes.INTEGER,
defaultValue: 0,
},
storeRating: {
type: DataTypes.INTEGER,
defaultValue: 0,
},
storeIsJoin: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
}, {
freezeTableName: true,
});
};
//ReviewModel.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('Review',{
reviewWriter :{
type: DataTypes.STRING(50),
allowNull: false,
},
reviewContent :{
type: DataTypes.STRING(200),
allowNull: false,
},
reviewGrade : {
type: DataTypes.INTEGER,
allowNull: false,
},
reviewIsDeclare : {
type: DataTypes.BOOLEAN,
allowNull: false,
},
}, {
freezeTableName: true,
});
};
//ReviewImage.js
module.exports = (sequelize, DataTypes) => {
return sequelize.define('ImageReview',{
reviewImageUrl :{
type: DataTypes.STRING(200),
allowNull: false,
},
}, {
freezeTableName: true,
});
};

sequelize - inner join gives an error after added a foreign key

i have these 2 models:
module.exports = function(sequelize, DataTypes) {
return sequelize.define('services_prices', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true
},
service_id: {
type: DataTypes.INTEGER(11),
allowNull: true,
references: {
model: 'services',
key: 'id'
}
},
created_at: {
type: DataTypes.DATE,
allowNull: false
},
limit: {
type: DataTypes.INTEGER(11),
allowNull: true
},
price: {
type: DataTypes.INTEGER(11),
allowNull: true
}
});
};
which is parent of this model: (services_user_prices can override services_prices )
module.exports = function(sequelize, DataTypes) {
return sequelize.define('services_user_prices', {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true
},
user_id: {
type: DataTypes.INTEGER(11),
allowNull: true
},
created_at: {
type: DataTypes.DATE,
allowNull: false
},
currency: {
type: DataTypes.STRING(255),
allowNull: true
},
is_active: {
type: DataTypes.INTEGER(1),
allowNull: true,
defaultValue: '0'
},
is_trial: {
type: DataTypes.INTEGER(1),
allowNull: true,
defaultValue: '0'
},
start_date: {
type: DataTypes.DATE,
allowNull: false
},
end_date: {
type: DataTypes.DATE,
allowNull: true
},
price: {
type: DataTypes.INTEGER(11),
allowNull: true
},
bundle_price_id: {
type: DataTypes.INTEGER(11),
allowNull: true,
references: {
model: 'services_prices',
key: 'id'
}
}
});
};
when trying to join them i get an error:
EagerLoadingError: services_prices is not associated to services_user_prices!
const result= await db.services_user_prices.findOne({
where: { is_active: 1, user_id: 123 }, include:[{db.services_prices}]
});
in the db services_user_prices has foreign key to services_prices table
what am i doing wrong?
Well if you are using sequelize then you need to update your model because
by default, sequelize will be looking for foreign key starts with model name like
you have defined bundle_price_id as a foreign key for services_prices.
You need to change your column name to services_price_id then it will get fixed.
or if you want to use bundle_price_id you need to define it in your model relation as.
Model.belongsTo(models.ModelName, { foreignKey: 'your_key'} )
Please feel free if you need to ask anything else.
As complement of the above answer you need to add an identifier with as: on the association like this:
Model.belongsTo(models.ModelName, { foreignKey: 'your_key', as:'your_identifier' } )
Then when you do the include on the method you also call the identifier:
await db.services_user_prices.findOne({
where: { is_active: 1, user_id: 123 },
include:[{
model: db.services_prices
as: 'your_identifier'
}]
});
If you don't define the foreignKey field, the as field will set the column name.

Sequelize saving many to many

I was wandering if there are any extended tutorials on how to save a many to many relationship? I find the documentation more than basic. Its missing many use case examples.
I have two models: Client and Rule. They have the n:n relationship.
Client:
var Client = sequelize.define('client', {
title: {
type: DataTypes.STRING(200),
allowNull: false
},
company: {
type: DataTypes.STRING(200),
allowNull: false
},
vendor: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
consumer: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true
},
address_id: {
type: DataTypes.INTEGER,
allowNull: true
}
},{
paranoid: true,
underscored: true,
classMethods: {
associate:function(models){
Client.hasMany(models.rule, { through: 'client_rules', onDelete: 'cascade'});
}
}
});
Rule:
var Rule = sequelize.define('rule', {
service_id: {
type: DataTypes.INTEGER,
allowNull: false
},
is_allowed: {
type: DataTypes.BOOLEAN,
defaultValue: false
},
valid_until: {
type: DataTypes.DATE,
allowNull: true,
},
rule: {
type: DataTypes.TEXT,
allowNull: true
},
type: {
type: DataTypes.INTEGER, // 1 for company rule, 2 for individual rule
allowNull: false,
},
active: {
type: DataTypes.BOOLEAN,
defaultValue: true
}
},{
underscored: true,
paranoid: true,
classMethods: {
associate:function(models){
Rule.belongsToMany(models.client, { through: 'client_rules', onDelete: 'cascade'});
Rule.belongsTo(models.service, { foreignKey: 'service_id' } );
}
}
});
Now I would like to create a new rule for client. So I would have to create the rule first and associate it then to the client through 'client_rules'.
How do I do that with sequelize? This doesn't work:
var clientID = req.user.client_id;
Client.find({ id: clientID })
.then(function(client){
return client.addRule(req.body)
})
.catch(function(err){
console.log(err)
})
[TypeError: Cannot read property 'replace' of undefined]
Ok I found out how to do it. The docs are very confusing.
var clientID = req.user.client_id;
return Rule.create(req.body)
.then(function(newRule){
var ruleToAdd = newRule;
return Client.findOne({ where: { id: clientID } })
.then(function(client){
return client.addRule(ruleToAdd)
.then(function(ans){
return ruleToAdd;
})
})

Resources