Error: XModel is not associated to Ymodel on Sequelizejs - node.js

I have a few weeks working with Sequelize and I ran into this. I've already read other similar questions but nothing seems to help.
Let me show you my models:
Merchants.js
'use strict';
var Sequelize = require('sequelize');
var config = require(__base + '/server/config/config').provisioning;
var sequelize = new Sequelize(config.database, config.user, config.password, config);
var Merchants = sequelize.define('merchants', {
id: {
type: Sequelize.UUID,
primaryKey: true,
unique: true,
defaultValue: Sequelize.UUIDV4
},
name: {
type: Sequelize.STRING(255)
},
createdAt: {
type: Sequelize.DATE,
field: 'created_at'
},
//more attributes
}, {
classMethods: {
associate: function (models) {
Merchants.hasOne(models.Users, {foreignKey: 'merchantId'})
}
}
});
module.exports = Merchants;
Users.js
'use strict';
var Sequelize = require('sequelize');
var config = require(__base + '/server/config/config').provisioning;
var sequelize = new Sequelize(config.database, config.user, config.password, config);
var Users = sequelize.define('users', {
id: {
type: Sequelize.UUID,
primaryKey: true,
unique: true,
defaultValue: Sequelize.UUIDV4
},
merchantId: {
type: Sequelize.UUID,
field: 'merchant_id'
},
createdAt: {
type: Sequelize.DATE,
field: 'created_at'
},
// more attributes
}, {
classMethods: {
associate: function (models) {
Users.belongsTo(models.Merchants, { foreignKey: 'merchantId' });
}
}
});
module.exports = Users;
Then I'm trying to do this:
Users.findAll({
include: [{
model: Merchants,
where: { state: 'ACTIVATED' }
}]
}).then(function (users) {
console.log(users.length);
}).catch(function (err) {
console.log(err);
});
And I'm getting: [Error: merchants is not associated to users!]
I've done some of the stuff I've read in different questions but nothing seems to work. It might be a foolish thing, but as I said before, first time working with Sequelize.

Make sure that the associations are actually being set up - Do note that the associate method is not part of sequelize API, but is merely a common pattern - you have to make sure its actually called. For example with:
fs
.readdirSync(__dirname)
.filter(function(file) {
return (file.indexOf(".") !== 0) && (file !== "index.js");
})
.forEach(function(file) {
var model = sequelize.import(path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(function(modelName) {
if ("associate" in db[modelName]) {
db[modelName].associate(db);
}
});
https://github.com/sequelize/express-example/blob/master/models/index.js

Related

TypeError: Class constructor model cannot be invoked without 'new'. I am not using typescript

I am new to sequelize orm.
While developing backend with express, sequelize and mssql, I created models with sequelize-cli.
Before I have index.js file and new models created by seqeulize-cli command 'sequelize init' and 'sequelize model:generate..", I had no issue.
But as I start the server I encountered the error saying "TypeError: Class constructor model cannot be invoked without 'new'".
I have not touched index.js file and the new model generated by sequelize-cli is class-basis.
I tried to change class-basis model to sequelize.define() but still get the same error.
Please help me resolve the issue.
Thanks!!
Here is my code.
index.js
"use strict";
const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const process = require("process");
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || "development";
const config = require(__dirname + "/../config/config.json")[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
} else {
}
fs.readdirSync(__dirname)
.filter((file) => {
return (
file.indexOf(".") !== 0 && file !== basename && file.slice(-3) === ".js"
);
})
.forEach((file) => {
console.log("##########", path.join(__dirname, 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;
GroupCode.js
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class GroupCode extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate({ CommonCode }) {
// define association here
this.hasMany(CommonCode);
}
}
GroupCode.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
description: {
type: DataTypes.STRING,
},
active: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
createdBy: {
type: DataTypes.STRING,
},
updatedBy: {
type: DataTypes.STRING,
},
},
{
sequelize,
modelName: "GroupCode",
}
);
return GroupCode;
};
CommonCode.js
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class CommonCode extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate({ GroupCode }) {
// define association here
this.belongsTo(GroupCode, {
foreignKey: { name: "groupCodeId", allowNull: false },
});
}
}
CommonCode.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
value: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
seq: {
type: DataTypes.INTEGER,
default: 1,
},
active: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
createdBy: {
type: DataTypes.STRING,
},
updatedBy: {
type: DataTypes.STRING,
},
},
{
sequelize,
modelName: "CommonCode",
}
);
return CommonCode;
};
Resolve the error that appears when start the server.

NodeJS PostgreSQL Express SequelizeEagerLoadingError on relationship table

I'm having a trouble where I couldn't access the relationship data table from NodeJS PostgreSQL and Express.
First of all here is my simple table :
As you can see, my "jenis" table has association with "kategori" table, one jenis can have multiple kategori, and one kategori should only contain one jenis.
Here is my migration on Postgres Sequelize :
jenis-migration.js
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("Umkm_Jenis", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
nama: {
type: Sequelize.STRING,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("Umkm_Jenis");
},
};
kategori-migration.js
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("Umkm_Kategori", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
jenis_id: {
type: Sequelize.INTEGER,
allowNull: false,
},
nama: {
type: Sequelize.STRING,
allowNull: false,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("Umkm_Kategori");
},
};
jenis.model.js
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Umkm_Jenis extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
this.hasMany(models.Umkm_Kategori, {
foreignKey: "jenis_id",
as: "umkm_kategori",
});
}
}
Umkm_Jenis.init(
{
nama: DataTypes.STRING,
},
{
sequelize,
modelName: "Umkm_Jenis",
freezeTableName: true,
}
);
return Umkm_Jenis;
};
kategori-model.js
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Umkm_Kategori extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
this.belongsTo(models.Umkm_Jenis, {
foreignKey: "jenis_id",
as: "umkm_jenis",
});
}
}
Umkm_Kategori.init(
{
jenis_id: DataTypes.INTEGER,
nama: DataTypes.STRING,
},
{
sequelize,
modelName: "Umkm_Kategori",
freezeTableName: true,
}
);
return Umkm_Kategori;
};
I have created some seeder data on postgres for both jenis and kategori table.
Now I want my getAllKategori API to actually include the value from "jenis" table using the relationship that I have made. Below is my apiController for kategori :
exports.findAllKategori = async (req, res) => {
//check if theres a filter applied
const nama = req.query.nama;
const condition = nama ? { nama: { [Op.iLike]: `%${nama}%` } } : null;
try {
const response = Kategori.findAll({
where: condition,
include: [{ model: db.jenis, as: "umkm_jenis", required: false }],
});
const data = await response;
return res.status(200).send(data);
} catch (error) {
console.log(error);
return res.status(500).send(error);
}
};
But when I tried to hit the API from POSTMAN, it shows SequelizeEagerLoadingError.
If I commented this line on kategoriController :
include: [{ model: db.jenis, as: "umkm_jenis", required: false }],
and then try to hit the api once more, it successfully shows all my data.
I have already read some similar question in this forum but none of it seems to work.
Thank you for taking your time!
UPDATE
Below is the models/index.js file
"use strict";
const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || "development";
const config = require(__dirname + "/../config/config.json")[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
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;
db.kategori = require("./umkm_kategori")(sequelize, Sequelize);
db.jenis = require("./umkm_jenis")(sequelize, Sequelize);
db.produk = require("./umkm_produk")(sequelize, Sequelize);
db.review = require("./umkm_review")(sequelize, Sequelize);
module.exports = db;
console.log(error)
You already registered all models and associations with this code pieces:
const model = require(path.join(__dirname, file))(
sequelize,
Sequelize.DataTypes
);
db[model.name] = model;
and
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
so this code is registering models once again, just remove it and use model names defined above.
db.kategori = require("./umkm_kategori")(sequelize, Sequelize);
db.jenis = require("./umkm_jenis")(sequelize, Sequelize);
db.produk = require("./umkm_produk")(sequelize, Sequelize);
db.review = require("./umkm_review")(sequelize, Sequelize);

Unhandled rejection SequelizeEagerLoadingError: is not associated to, and Cannot read property 'getTableName' of undefined

I have 3 tables: User, Trip, authoriseDate.
here is associate:
A user has many trips and a user has one authoriseDate
User one to many Trips
User one to one authoriseDate
and here is the models
User
module.exports = (sequelize, DataTypes) => {
const user = sequelize.define('User', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
email: { type: DataTypes.STRING(50), unique: true },
phoneNumber: {
type: DataTypes.STRING(12), unique: true,
},
}, {
classMethods: {
associate(models) {
// associations can be defined here
user.hasOne(models.authoriseDate, { foreignKey: 'userId' });
user.hasMany(models.Trip, { foreignKey: 'userId' });
},
},
});
return user;
};
Trip
module.exports = (sequelize, DataTypes) => {
const trip = sequelize.define('Trip', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
userId: DataTypes.INTEGER,
status: DataTypes.INTEGER,
}, {
classMethods: {
associate(models) {
// associations can be defined here
trip.belongsTo(models.User, { foreignKey: 'userId' });
},
},
});
return trip;
};
authoriseDate
module.exports = (sequelize, DataTypes) => {
const authoriseDate = sequelize.define('AuthoriseDate', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
userId: DataTypes.INTEGER,
lastAuthorise: DataTypes.DATE,
}, {
classMethods: {
associate(models) {
// associations can be defined here
authoriseDate.belongsTo(models.User, { foreignKey: 'userId', });
},
},
});
return authoriseDate;
};
but when I using findAll function
models.User.findAll({
include: [{
model: models.Trip,
},
{
model: models.authoriseDate,
}],
})
here is my model file
'use strict';
var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var basename = path.basename(module.filename);
//var env = process.env.NODE_ENV || 'development';
//var config = require(__dirname + './../../../config/config.json')[env];
var config = require('../../config/env')
var db = {};
// if (config.use_env_variable) {
// var sequelize = new Sequelize(process.env[config.use_env_variable]);
// } else {
// var sequelize = new Sequelize(config.database, config.username, config.password, config);
// }
var sequelize = new Sequelize(config.dbName, config.dbUserName, config.dbPassword, {
host: config.dbHost,
dialect: config.dbDialect,
});
fs
.readdirSync(__dirname)
.filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== basename);
})
.forEach(function (file) {
if (file.slice(-3) !== '.js') return;
var 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;
I am getting the errors:
Unhandled rejection SequelizeEagerLoadingError: Trip is not associated to User, and Cannot read property 'getTableName' of undefined
I don't know how to solve these errors, anyone help me please
You need to call a function associate.
Example:
AuthoriseDate model
module.exports = (sequelize, DataTypes) => {
const authoriseDate = sequelize.define('AuthoriseDate', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
userId: DataTypes.INTEGER,
lastAuthorise: DataTypes.DATE,
});
authoriseDate.associate = (models) => {
// associations can be defined here
authoriseDate.belongsTo(models.User, { foreignKey: 'userId', });
};
return authoriseDate;
};
Trip Model
module.exports = (sequelize, DataTypes) => {
const trip = sequelize.define('Trip', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
userId: DataTypes.INTEGER,
status: DataTypes.INTEGER,
});
trip.associate = (models) => {
// associations can be defined here
trip.belongsTo(models.User, { foreignKey: 'userId' });
};
return trip;
};
User Model
module.exports = (sequelize, DataTypes) => {
const user = sequelize.define('User', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
email: { type: DataTypes.STRING(50), unique: true },
phoneNumber: {
type: DataTypes.STRING(12), unique: true,
},
});
user.associate = (models) => {
// associations can be defined here
user.hasOne(models.AuthoriseDate, { foreignKey: 'userId' });
user.hasMany(models.Trip, { foreignKey: 'userId' });
};
return user;
};
init models
'use strict';
var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var basename = path.basename(module.filename);
//var env = process.env.NODE_ENV || 'development';
//var config = require(__dirname + './../../../config/config.json')[env];
// var config = require('../../config/env')
var db = {};
var sequelize = new Sequelize('test_01', 'root', 'root', {
host: 'localhost',
dialect: 'mysql',
});
fs
.readdirSync(__dirname)
.filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== basename);
})
.forEach(function (file) {
if (file.slice(-3) !== '.js') return;
var model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
console.log(db);
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
(async () => {
await sequelize.sync();
})();
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
use find
(async () => {
const models = require('./models');
const users = await models.User.findAll({
include: [
{
model: models.Trip,
},
{
model: models.AuthoriseDate,
},
],
});
console.log(users);
})();
http://docs.sequelizejs.com/manual/tutorial/associations.html

Update with association using Sequelize.js

I am trying to update with association using sequelize.js.
I have tried give example on stackoverflow namely the following links:
Sequelize update with association
Sequelize update with association
Updating attributes in associated models using Sequelize
all of these links did not get me to the goal i am trying to accomplish.
My model is as follow, I have a country module and a city module. a country has many cities. please refer to the module bellow.
Please advise.
country.js file
module.exports = function (sequelize, DataTypes) {
var country= sequelize.define('COUNTRY', {
COUNTRY_ID: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
COUNTRY_NAME: DataTypes.STRING,
COUNTRY_CURRENCY: DataTypes.STRING
}, {
freezeTableName: true,
classMethods: {
associate: function (models) {
COUNTRY_ID.hasMany(models.CITIES, {
foreignKey: 'COUNTRY_ID'
})
}
},
instanceMethods: {
updateAssociation: function (onSuccess, onError) {
country.findAll({
where: {
COUNTRY_ID: req.params.country_id
},
include: [
{
model: sequelize.import('./cities.js'),
}
]
})
})
.then(country =>{
const updatePromises = country.map(countries =>{
return countries.updateAttributes(req.body);
});
const updatePromisescities = list.CITY.map(cities =>{
return cities.updateAttributes(req.body.CITYs[0]);
});
return sequelize.Promise.all([updatePromises, updatePromisescities ])
}).then(onSuccess).error(onError);
}
}
});
return country;
};
city.js file
module.exports = function (sequelize, DataTypes) {
var CITY = sequelize.define('LIST_CODE', {
CITY_ID: {
type: DataTypes.INTEGER,
primaryKey: true
},
COUNTRY_ID: {
type: DataTypes.INTEGER,
primaryKey: true
}
}, {
freezeTableName: true,
timestamps: false,
classMethods: {
associate: function (models) {
// associations can be defined here
CITY.belongsTo(models.COUNTRY, {
foreignKey: 'COUNTRY_ID'
})
}
}
});
return CITY;
};

Sequelize TypeError Associate is not a Function

I am creating a one-to-many relationship and ran into a strange error when I pass the associated model to my db object. I don't understand where the error will come from as the method follows the documentation. Do I need to write a reference within my targeted model?
Error:
db.DiscoverySource.associate(db);
^
TypeError: db.DiscoverySource.associate is not a function
at Object.<anonymous> (/Users/user/Desktop/Projects/node/app/app/models/db-index.js:33:20)
Source Model (One) organization.js:
module.exports = function(sequelize, DataTypes) {
var Organization = sequelize.define('organization', {
organizationId: {
type: DataTypes.INTEGER,
field: 'organization_id',
autoIncrement: true,
primaryKey: true
},
organizationName: {
type: DataTypes.STRING,
field: 'organization_name'
},
admin: DataTypes.STRING
},{
freezeTableName: true,
classMethods: {
associate: function(db) {
Organization.belongsToMany(db.User, { through: 'member', foreignKey: 'user_id' }),
Organization.hasMany(db.DiscoverySource, { foreignKey: 'organization_id' });
},
}
});
return Organization;
}
Target (Many) discovery-source.js:
module.exports = function(sequelize, DataTypes) {
var DiscoverySource = sequelize.define('discovery_source', {
discoverySourceId: {
type: DataTypes.INTEGER,
field: 'discovery_source_id',
autoIncrement: true,
primaryKey: true
},
discoverySource: {
type: DataTypes.STRING,
field: 'discovery_source_name'
},
organizationId: {
type: DataTypes.TEXT,
field: 'organization_id'
},
},{
freezeTableName: true,
});
return DiscoverySource;
}
db-index.js joining the models:
var Sequelize = require('sequelize');
var path = require('path');
var config = require(path.resolve(__dirname, '..', '..','./config/config.js'));
var sequelize = new Sequelize(config.database, config.username, config.password, {
host:'localhost',
port:'3306',
dialect: 'mysql'
});
sequelize.authenticate().then(function(err) {
if (!!err) {
console.log('Unable to connect to the database:', err)
} else {
console.log('Connection has been established successfully.')
}
});
var db = {}
db.Member = sequelize.import(__dirname + "/member");
db.Organization = sequelize.import(__dirname + "/organization");
db.User = sequelize.import(__dirname + "/user");
db.DiscoverySource = sequelize.import(__dirname + "/discovery-source");
db.User.associate(db);
db.Organization.associate(db);
db.DiscoverySource.associate(db);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
sequelize.sync();
module.exports = db;
You're getting an error because you haven't defined associate in classMethods for DiscoverySource. It looks like you don't need to call that, so just remove that line altogether.

Resources