Model not getting imported as a Sequelize.Model - javascript

I'm trying to use a sequelize N:M relation trough another table but I keep getting this error:
throw new Error(${this.name}.belongsToMany called with something that's not a subclass of Sequelize.Model);
Error: Cases.belongsToMany called with something that's not a subclass of Sequelize.Model
Here are my classes:
models/User.js
const Sequelize = require('sequelize');
const sql = require('../config/sql');
const DocumentType = require('./DocumentType');
const Case = require('./Case');
const User = sql.define('Users', {
firstName: Sequelize.STRING,
lastName: Sequelize.STRING,
email: Sequelize.STRING,
document: Sequelize.INTEGER,
documentTypeId: Sequelize.INTEGER,
password: Sequelize.STRING,
active: Sequelize.INTEGER
});
User.belongsTo(DocumentType, {foreignKey: 'documentTypeId' ,as: 'documentType'});
User.belongsToMany(Case, { through: 'CaseUser' });
User.findById = (id) => {
return User.findOne({
where: {
id: id
},
include: 'documentType'
});
};
User.findByEmail = (email) => {
return User.findOne({
where: {
email: email
},
include: 'documentType'
});
};
User.checkActiveStatus = (id) => {
return User.findOne({
where: {
id: id
},
attributes: ['active']
});
};
module.exports = User;
models/Case.js
const Sequelize = require('sequelize');
const sql = require('../config/sql');
const User = require('./User');
const Case = sql.define('Cases', {
description: Sequelize.STRING,
startDate: Sequelize.STRING
});
Case.belongsToMany(User, {through: 'CaseUser'});
module.exports = Case;
I get the error only in the Case.belongsToMany(User, { through: 'CaseUser' }); and not in the User.belongsToMany(Case, { through: 'CaseUser' }); one
The weird thing is that if I switch the belongsToMany(User... for belongsToMany(DocumentType... and import the DocumentType file I don't get the error. The DocumentType Model is virtually identical to the User one
models/DocumentType.js
const Sequelize = require('sequelize');
const sql = require('../config/sql');
const DocumentType = sql.define('DocumentTypes', {
name: Sequelize.STRING,
slug: Sequelize.STRING
}, {
timestamps: false
});
module.exports = DocumentType;
Any ideas on what could be causing this behavior?
Thanks!

You should try to avoid circular dependencies.
Remove lines
const Case = require('./Case');
and
Case.belongsToMany(User, {through: 'CaseUser'});
from User.js
Remove lines
const User = require('./User');
and
User.belongsToMany(Case, { through: 'CaseUser' });
from Case.js
Create associations.js
const Case = require('./Case');
const User = require('./User');
Case.belongsToMany(User, {through: 'CaseUser'});
User.belongsToMany(Case, { through: 'CaseUser' });

Related

How to do a Many to Many relationship in Sequelize?

These are my models:
Staff
const { DataTypes } = require('sequelize');
const sequelize = require('../sequelize')
const Staff = sequelize.define('Staff', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
SSN: {
type: DataTypes.INTEGER,
},
email:{
type: DataTypes.STRING,
}
}, {
timestamps: true
});
Staff.associate = function (models) {
Staff.belongsToMany(models.Technology, {through: models.StaffTechnology});
};
module.exports = Staff;
Technology:
const { DataTypes } = require('sequelize');
const sequelize = require('../sequelize')
const Technology = sequelize.define('Technology', {
name: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.STRING,
}
}, {
timestamps: true
});
Technology.associate = function (models) {
Technology.belongsToMany(models.Staff, { through: models.StaffTechnology});
};
module.exports = Technology;
This will be the join table:
const { DataTypes } = require('sequelize');
const sequelize = require('../sequelize')
const Staff = require('../../database/models/staff.model');
const Technology = require('../../database/models/technology.model');
const StaffTechnology = sequelize.define('StaffTechnology', {
experience: {
type: DataTypes.INTEGER,
},
StaffID: {
type: DataTypes.INTEGER,
references: {
model: Staff,
key: 'id'
}
},
TechnologyID: {
type: DataTypes.INTEGER,
references: {
model: Technology,
key: 'id'
}
},
}, {
timestamps: true
});
StaffTechnology.associate = function (models) {
//StaffTechnology.hasMany(models.Staff, { foreignKey: 'StaffID' });
//StaffTechnology.hasMany(models.Technology, { foreignKey: 'TechnologyID' });
};
module.exports = StaffTechnology
Right now I cant do a Staff.findAll({include:Technology}), since it give me an error saying that Staff and Technology are not associated, but I saw Sequelize documentation, and I saw a very similar example working.
What I want is the posibility to return All Staffs with their technologies, Staff can have many technologies, and Technologies can belong to Many Staffs, but in reality they are connected through StaffTechnology join table.
You need to declare the associations inside of your index.js (or where you initialize your DB). You can either do it manually by declaring the associations directly by requiring the models and doing
Model1.association(Model2, {
through: "JoinTable"
}
Model2.association(Model1, {
through: "JoinTable"
}
Or do it programmatically (If you are already using that approach to initialize your DB):
'use strict'
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const config = {
"username": "root",
"password": "YOUR ROOT PASSWORD HERE",
"database": "YOUR DATABASE NAME HERE",
"host": "127.0.0.1",
"dialect": "mysql"
}
const db = {}
let sequelize = new Sequelize(config.database, config.username, config.password, config);
fs.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0)
&& (file !== basename)
&& (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
^ This code does both the initialization and the associations in one. You need to make sure that your model files and the initialization file are in the same folder.

Module export return me a function

This is my Cliente.js that its a model
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
const cliente = sequelize.define('cliente', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
nombre: {
type: DataTypes.STRING(20),
allowNull: true
}
}, {
sequelize,
tableName: 'cliente',
timestamps: false,
indexes: [
{
name: "PRIMARY",
unique: true,
using: "BTREE",
fields: [
{ name: "id" },
]
},
]
});
return cliente;
};
and that is my app.js
var express = require('express');
const Sequelize = require('sequelize');
const Cliente = require("./Modelos/cliente")
var app = express();
const db = require("./database/db")
db.sequelize.authenticate().then(() => {
console.log('Connection has been established successfully.');
console.log(Cliente)
}).catch(err => {
console.error('Unable to connect to the database:', err);
});
The line "console.log(Cliente) returns me "[Function]" and not the model.
how can i get the model and not the function?
So try changing this line
module.exports = function(sequelize, DataTypes) {
To
exports.sequ = function(sequelize, DataTypes) {
Then
Change
const Cliente = require("./Modelos/cliente");
And this line to
console.log(Cliente.sequ)
I would suggest rereading how to work with sequelize and rewrite the codebase.
Cliente.js - exports the function with has 2 parameters.
console.log(Cliente) - doesn't pass any parameters. Thus how the magic should happen?
Cliente.js - const Sequelize = require('sequelize') is not used.
The models must be defined on the sequelize instance which you are using also connect to DB.
//Cliente.js
const DataTypes = require("sequelize");
const cliente = sequelize => {
const res = sequelize.define('cliente', {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true
},
nombre: {
type: DataTypes.STRING(20),
allowNull: true
}
}, {
sequelize,
tableName: 'cliente',
timestamps: false,
indexes: [
{
name: "PRIMARY",
unique: true,
using: "BTREE",
fields: [
{ name: "id" },
]
},
]
});
return res;
};
module.exports = cliente
and
// index.js
const Sequelize = require('sequelize')
const sequelize = new Sequelize('postgres://<username>:<password>#<host>:<port>/<db_name>')
;(async () => {
await sequelize.authenticate()
const Cliente = require("./cliente")
const cliente = Cliente(sequelize)
console.log(cliente)
})()

Relation between Users and cryptodata Sequelize database

I'm trying to build a relation between the users and his favorite cryptocurrency.
Meaning, multiple Users can have the same crypto as their favorites.
Coin.js
module.exports = (sequelize, DataTypes) => {
const Coin = sequelize.define('Coin', {
cryptoName: DataTypes.STRING,
})
Coin.associate = function(models) {
Coin.belongsToMany(models.CoinsUserRelations, {foreignKey: 'CoinID', through: 'CoinsUserRelations'})
}
return Coin
}
User.js
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
email: {
type: DataTypes.STRING,
unique: true
},
password: DataTypes.STRING
}, {
hooks: {
beforeSave: hashPassword
}
})
User.associate = function(models) {
User.belongsToMany(models.CoinsUserRelations, {foreignKey: 'UserID', through: 'CoinsUserRelations'})
}
return User
}
These are my 2 tables at the moment and now I'm trying to build a relation between them. and I keep receiving this error on my console which I do not understand why.
I've edited multiple time to resolve the issue, This was the result with the help of Anatoly
CoinsUserRelations.js
module.exports = (sequelize, DataTypes) => {
const CoinsUsersRelations = sequelize.define('CoinsUsersRelations', {
UserID: {
type: DataTypes.INTEGER,
},
CoinID: {
type: DataTypes.INTEGER,
}
})
return CoinsUsersRelations
}
I'm really unsure on why I get this error if I'm actually defining the model before creating the relations..
Index.js
const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
const config = require('../config/config')
const db = {}
const sequelize = new Sequelize(
config.db.database,
config.db.user,
config.db.password,
config.db.options
)
fs
.readdirSync(__dirname)
.filter((file) =>
file !== 'index.js'
)
.forEach((file) => {
const model = sequelize.import(path.join(__dirname, file))
db[model.name] = model
})
Object.keys(db).forEach(function (modelName) {
if (db[modelName].associate) {
db[modelName].associate(db)
}
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db
Edit part for a bug called SequelizeEagerLoadingError
module.exports = {
async getUserFavoriteCrypto (req, res) {
try {
const coins = await db.Users.findOne({
where: {
UserID : req.query.userId
},
attributes: ['UserID'],
include: [{
model: db.Coins,
required: false
}]
})
console.log(coins)
res.send({
coins: coins
})
} catch (err) {
res.status(400).send({
error: err
})
}
}
}
You should register all models and only after that all their associations in one place. See my answer on a similar problem

Sequelize assocation functions have no effect

I use the present Sequelize version and try to build the associations between two models. Should be actually pretty simple since Sequelize offers hasMany and belongsTo.
But the call has no effect at all. I tried it with a new SQL DB. The tables itself are created, just without any foreign key.
db controller
const userModel = require('../model/user')
const subjectModel = require('../model/subject')
const database = require('../db/database').sequeliceInstance
async function setupAssociations () {
await database.sync()
// user + subject
userModel.hasMany(subjectModel)
subjectModel.belongsTo(userModel)
// subject and topic
subjectModel.hasMany(topicModel)
topicModel.belongsTo(subjectModel)
// topic and question
topicModel.hasMany(questionModel)
questionModel.belongsTo(topicModel)
// question and answer
questionModel.hasMany(answerModel)
answerModel.belongsTo(questionModel)
return Promise.resolve()
}
user.js
const Sequelize = require('sequelize')
const db = require('../db/database').sequeliceInstance
const user = db.define('user', {
// attributes
firstName: {
type: Sequelize.STRING,
allowNull: false
},
lastName: {
type: Sequelize.STRING,
allowNull: false
},
email: {
type: Sequelize.STRING,
allowNull: false
},
title: {
type: Sequelize.STRING,
allowNull: false
},
password: {
type: Sequelize.TEXT,
allowNull: false
}
})
module.exports = user
subject.js
const Sequelize = require('sequelize')
const db = require('../db/database').sequeliceInstance
const subject = db.define('subject', {
// attributes
subjectName: {
type: Sequelize.TEXT,
allowNull: false
}
})
module.exports = subject
I found the solution.
await database.sync() has to be called at the very end of the function.

I can not create a "researcher" using the sequelize

I try to create a new researcher but I just go into catch, and I do not get any errors. I am new using sequelize, I need a lot of help for this problem, my complete code in git: https://github.com/chanudinho/RevYou-BackEnd.
I can't explain it better, please if you need to download the project and test it. Sorry for my english =x
researcherController.js
const Researcher = require('../../sequelize/models/researcher');
const createResearcher= async (req, res) => {
try{
Researcher.create({name: 'name', email: 'email', password: 'password'});
return res.status(201).send('sucesso');
}catch (err){
return res.status(500).send('error');
}
}
models/researcher.js
module.exports = (sequelize, DataTypes) => {
const Researcher = sequelize.define('Researcher', {
name: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING
});
return Researcher;
};
migrations/20190114200431-create-researcher
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Researcher', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
name: {
allowNull: false,
type: Sequelize.STRING
},
email: {
allowNull: false,
type: Sequelize.STRING
},
password:{
allowNull: false,
type: Sequelize.STRING
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Researcher');
}
};
models/index.js
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const config = require('../../config/database.js');
const db = {};
const sequelize = new Sequelize(config);
fs
.readdirSync(__dirname)
.filter(file => (file.indexOf('.') !== 0) && (file !== path.basename(__filename)) && (file.slice(-3) === '.js'))
.forEach((file) => {
const model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
The problem is that you are importing the model file and this is not right, your index.js within model maps all model files by adding the sequelize instance and the datatypes. You should always import the index.
If you import the model index and give a console.log() in it will see that you have the object of your model and the instance of the sequelize.
const db = require('../../sequelize/models/index');
console.log(db)
Inside the exit will have something like this: Example:
Researcher: Researcher,
sequelize:
Sequelize { ....
To access your model you can do the following. By using destructuring assignment, you extract the model from within the index.
Result
const { Researcher } = require('../../sequelize/models/index')
const createResearcher= async (req, res) => {
try{
await Researcher.create({name: 'name', email: 'email', password: 'password'});
return res.status(201).send('sucesso')
}catch (err){
return res.status(500).send('error');
}
}
Whenever you create a new file inside the model folder, it will be mapped by index.js and added inside the matrix and using destructuring you can access or use the matrix key itself.
const db = require('../../sequelize/models/index')
const createResearcher= async (req, res) => {
try{
await db.Researcher.create({name: 'name', email: 'email', password: 'password'});
return res.status(201).send('sucesso')
}catch (err){
return res.status(500).send('error');
}
}

Categories

Resources