Unhandled rejection SequelizeEagerLoadingError in sequelize - Nodejs - mysql

This is my parent model Providers
module.exports = function(sequelize, DataTypes) {
const Providers = sequelize.define('Providers', {
provider_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
provider_name: DataTypes.STRING,
address: DataTypes.STRING,
city: DataTypes.STRING,
state: DataTypes.STRING,
zip: DataTypes.STRING,
phone: DataTypes.STRING,
website: DataTypes.STRING,
accepting_new_clients: DataTypes.INTEGER
});
Providers.associate = models => {
Providers.belongsTo(model.Providerclients, {foreignKey: "provider_id" })
}
return Providers;
}
This is my child model Providerclients
module.exports = function(sequelize, DataTypes) {
const Providerclients = sequelize.define('provider_clients', {
provider_client_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
provider_id: DataTypes.INTEGER,
client_id: DataTypes.INTEGER
},{});
Providerclients.associate = (models) => {
Providerclients.belongsToMany(models.Providers, {foreignKey: "provider_id"});
};
return Providerclients;
}
This is my other child model Providerinsurance
module.exports = function(sequelize, DataTypes) {
const Providerinsurance = sequelize.define('provider_insurance', {
provider_insurance_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
provider_id: DataTypes.INTEGER,
insurance_id: DataTypes.INTEGER
},{});
return Providerinsurance;
}
I am trying to get data from providers table joining the provider clients table.
To be clear I want to run the below query in mysql format
select * from providers as p left join provider_clients as pc on p.provider_id = pc.provider_id left join provider_insurance as pi on p.provider_id = pi.provider_id
I tried to join in sequelize as you can see in Providers and Providerclients models. I got the below error
Unhandled rejection SequelizeEagerLoadingError: provider_clients is not associated to Providers!

These is an association issue in your structure. Change your association to hasMany.
provider.hasMany(clientProvider)
This will add provider id into client provider.
http://docs.sequelizejs.com/manual/associations.html#one-to-many-associations--hasmany-
Here is a summary
Player.belongsTo(Team) // `teamId` will be added on Player / Source model
User.belongsTo(Company, {foreignKey: 'fk_company'}); // Adds fk_company to User
User.belongsTo(Company, {foreignKey: 'fk_companyname', targetKey: 'name'}); // Adds fk_companyname to User
========================================================================
Coach.hasOne(Team) // `coachId` will be added on Team / Target model
============================================================================
Project.hasMany(User)
This will add the attribute projectId or project_id to User. Instances of Project will get the accessors getWorkers and setWorkers.
Project.hasOne(User)
hasOne will add an attribute projectId to the User model!

Related

hasOne association in sequelize making multiple copies

So I am working on a project with Users, Products Carts, etc. And I am using sequelize to maintain a one-to-one relation between my User and the cart associated with it. I only want one Cart to be there for one User
User.hasOne(Cart);
Cart.belongsTo(Product);
sequelize.sync().then(
result=>{
return User.findByPk(1)
}
).then(user=>{
if(!user){
return User.create({
name: "Ary",
email: "test#test.com",
})
}
return user;
}).then(user=>{
console.log("here");
return user.createCart();
}).then(cart=>{
console.log("cartmain:");
console.log(cart);
app.listen(3000);
})
.catch(err => {console.log(err);})
I am currently working with only 1 default user, and by using the code above I am ensuring that the user is available and when it is confirmed I create a basket for that user using user.createCart() .
But whenever I run my code a new cart for that user gets created whereas I dont want that and dont expect that to happen as I am using one-to-one relation
Below are the models for my User and Cart:
const Sequelize = require('sequelize');
const sequelize = require('../util/database');
const User = sequelize.define('user', {
id:{
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
email:{
type: Sequelize.STRING,
allowNull: false
}
})
module.exports = User;
const Sequelize = require('sequelize');
const sequelize = require("../util/database");
const Cart = sequelize.define('cart', {
id:{
type: Sequelize.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true
}
})
module.exports = Cart
What can be done so that if a cart is not associated with a User it gets created if one is then it doesn't using sequelize

Sequelize in Nodejs creating duplicate tables upon app start

Ok. Landscape: Node, MySql, Sequelize
Issue: After creating a new data model & migration (node migrate.js which creates just fine), upon app start Sequelize creates a duplicate Table (and also forwards form data to the new table).
Ex: db.virtual_class is the main table, and upon start, db.virtual_classes is also created.
My model:
const Sequelize = require('sequelize');
const sequelize = require('../sequelize');
const model = sequelize.define('virtual_class', {
id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true },
style: Sequelize.STRING, // e.g. Style of class
description: Sequelize.STRING(1024), // e.g. class Details
jwt_secret: Sequelize.STRING, // e.g. rando string to be used to gen unique keys for every room
});
module.exports = model;
I've isolated what I think is the issue - I'm including the model in a variable on my index controller for my functions.
const Virtual_class = require('./model');
const classQuery = require('./classQuery');
async function addClass({ style, description, secret }) {
const vClass = await Virtual_class.create({
style,
description,
jwt_secret: secret,
}, { raw: true });
return classQuery(vClass);
}
module.exports = {
addClass,
};
Class Query function to return the data in a usable object:
function classQuery(queryResult) {
if (!queryResult) {
return null;
}
return {
id: queryResult.id,
style: queryResult.style,
description: queryResult.description,
secret: queryResult.jwt_secret,
};
}
module.exports = classQuery;
and the migration:
module.exports = {
up: (sequelize, Sequelize) => sequelize.getQueryInterface().createTable('virtual_class', {
id: {
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
style: {
type: Sequelize.STRING,
},
description: {
type: Sequelize.STRING,
},
jwt_secret: {
type: Sequelize.STRING,
},
createdAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('now'),
},
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.fn('now'),
},
}),
down: sequelize => sequelize.getQueryInterface().dropTable('virtual_class'),
};
Net result is fine before I run app - DB shows new table, After running app - DB shows dup table.
I'm a relative noob, and been wracking my brain (and trying to find solutions here) to the problem. I've done this before with other migrations with no issue.
Any advice is appreciated! Thanks!
DOH! For those who are new like me - Sequelize automatically creates plural tables by default, You can force the override tp singular table names.

Association without foreign keys and make join in table

I am working on Node + sequelize + mysql. All the things is working fine in my code. Now i need to add search field in list page. In this search page there is showing user first name, last name, company name and status. I got all data from one table but company comes from "Company" table. In user table there is company_id. I can not make association for company_id. Now i want to search from company_name too. How i add include without association.
const { User, Company } = require("../models");
if(query.trim() != "") {
[err, users] = await to(User.findAll({
where : {[Op.or] : {first_name:{ [Op.like]: '%'+query.trim()+'%' },last_name:{ [Op.like]: '%'+query.trim()+'%' }}},
include : [
{
model:Company,
where : {company_name:{ [Op.like]: '%'+query.trim()+'%' }}
}],
limit: 5,
offset: 0,
order: [[id, ASC]]
}));
console.log('err ----------------',err);
console.log(users);
}
I got below error on from above code :
err ---------------- { filename:
'/var/www/html/fullproject-name/backend/node_modules/sequelize/lib/model.js',
line: 583,
row: 13,
message: 'Company is not associated to User!',
type: 'SequelizeEagerLoadingError',
stack:
'SequelizeEagerLoadingError: Company is not associated to User!\n at Function._getIncludedAssociation..... }
User Model Code :
module.exports = (sequelize, DataTypes) => {
var Model = sequelize.define('User', {
email: {type: DataTypes.STRING, allowNull: true, unique: true, validate: { isEmail: {msg: "Phone number invalid."} }},
company_id: DataTypes.INTEGER,
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
active:DataTypes.INTEGER,
});
}
Company Model Code :
module.exports = (sequelize, DataTypes) => {
var Model = sequelize.define('Company', {
company_name: DataTypes.STRING,
company_attachment: DataTypes.STRING,
});
}
You need to associate your models with each other in order to be able to query them together with joins. In the below sample, I added some associations for User and Company. The relation I defined (which you can change) is one to many. A user belongs to one company; a company has many users.
This association will put a foreign key of company_id on the User model.
const models = require("./models.js") // Update if necessary
module.exports = (sequelize, DataTypes) => {
var User = sequelize.define("User", { // Changed from Model to User
email: {
type: DataTypes.STRING,
allowNull: true,
unique: true,
validate: { isEmail: { msg: "Phone number invalid." } }
},
company_id: DataTypes.INTEGER,
first_name: DataTypes.STRING,
last_name: DataTypes.STRING,
active: DataTypes.INTEGER
});
User.belongsTo(models.Company); // User to Company association
};
const models = require("./models.js") // Update if necessary
module.exports = (sequelize, DataTypes) => {
var Company = sequelize.define("Company", { // Changed from Model to Company
company_name: DataTypes.STRING,
company_attachment: DataTypes.STRING
});
Company.hasMany(models.User); // Company to User association
};

Async await in mysql seeding does not run

I am trying to seed my MySQL database. I am using the Sequelize ORM. In my index.js file which is in the models folder, I have the code to run the realSync() function for every model as such :
const syncDB = async () => {
await db['Meal'].realSync();
await db['User'].realSync();
}
syncDB();
And in my 'Meal' file, I have the following:
const mealSeeds = require("../scripts/mealSeeds");
module.exports = (sequelize, DataTypes) => {
let Meal = sequelize.define("Meal", {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: DataTypes.STRING,
type: DataTypes.STRING,
description: DataTypes.STRING,
photo_URL: DataTypes.STRING,
allergen_dairy: DataTypes.BOOLEAN,
allergen_treenuts: DataTypes.BOOLEAN,
allergen_peanuts: DataTypes.BOOLEAN,
allergen_wheat: DataTypes.BOOLEAN,
allergen_fish: DataTypes.BOOLEAN,
allergen_crustaceanshellfish: DataTypes.BOOLEAN,
allergen_eggs: DataTypes.BOOLEAN,
allergen_soya: DataTypes.BOOLEAN,
date_available: DataTypes.DATE,
time_available: DataTypes.TIME,
quantity: DataTypes.INTEGER,
zipcodes: DataTypes.JSON,
catererId: {
field: "CatererId",
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: 0
}
})
Meal.associate = function (models) {
Meal.belongsTo(models.User, {
foreignKey: "catererId",
targetKey: "id"
})
}
// // Insert the meal seed data
Meal.realSync = async () => {
await Meal.sync()
return await Meal.bulkCreate(mealSeeds,
{ignoreDuplicates: true}
);
};
return Meal;
}
Where the Meal.realSync is supposed to seed the Meals table with data from the mealSeeds.js file in the scripts directory. (And I have a User.js file with the user table fields and a similar .realSync() function for the User table. And this function is working just fine, and users are being seeded into the db).
This function was working fine for weeks, as I was building the project, and recently after changing some of the fields in the 'Meal' table, it no longer works. My previous research shows that by calling the realSync() function asynchronously in the index.js file, it will run and wait for the Meal realSync() function to complete before running the User realSync() function. I am not sure why it no longer runs the first function at all. Any help would be greatly appreciated.
Solved-I figured out that my seed data did not contain a foreign key reference.

Sequelize Many To Many Relationship : Cannot read property 'split' of undefined

I'm trying to create many to many relationship using Sequelize + nodeJs using existing MySQL Database :
Below is my tables :
- "usr" Table : usr_id (PK)
- Intermediate "usr_role" : usr_id, role_id
- "role" table : role_id
This is my models
"User" Models:
"use strict";
var bcrypt = require('bcryptjs');
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('User', {
usrid : {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
field:'usr_id'
},
name :{
type: DataTypes.STRING,
allowNull: false,
field:'usr_name'
},
}, {
timestamps: false,
freezeTableName: true,
tableName: 'usr',
name:'User',
underscored:'true',
classMethods: {
associate:function(models){
User.belongsToMany(models.Role, { through: 'UserRole', foreignKey:'usr_id', as:'UserRoles'});
}
}
}
);
return User;
};
"Role" models
module.exports = function(sequelize, DataTypes) {
var Role = sequelize.define('Role', {
id : {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
field:'role_id'
},
name :{
type: DataTypes.STRING,
allowNull: false,
field:'role_name'
},
},{
timestamps: false,
freezeTableName: true,
tableName: 'role_ref',
underscored:'true',
classMethods: {
associate:function(models){
Role.belongsToMany(models.User, {
through: 'UserRole',
foreignKey:'role_id'});
}
}
}
)
return Role;
};
E:\nodejsWS\learn\node_modules\inflection\lib\inflection.js:795
var str_path = str.split( '::' );
^
TypeError: Cannot read property 'split' of undefined
at Object.inflector.underscore
(E:\nodejsWS\learn\node_modules\inflection\lib\inflection.js:795:25)
at Object.module.exports.underscoredIf
(E:\nodejsWS\learn\node_modules\sequelize\lib\utils.js:28:27)
at new BelongsToMany (E:\nodejsWS\learn\node_modules\sequelize
\lib\associations\belongs-to-many.js:134:15)
at Mixin.belongsToMany
(E:\nodejsWS\learn\node_modules\sequelize\lib\associations
\mixin.js:264:21)
at sequelize.define.classMethods.associate
(E:\nodejsWS\learn\models\Role.js:29:12)
at E:\nodejsWS\learn\models\index.js:50:21
this is my index.js
// Import models
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;
});
//associate models
Object.keys(db).forEach(function(modelName) {
if ("associate" in db[modelName]) {
console.log(db);
db[modelName].associate(db);
}
});
Line 50 refer to db[modelName].associate(db), that cause the error.
Can somebody please guide me what's i'm doing wrong. Do i need to manually create intermediate Models 'UserRole'. Your help is very much appreciated. Thanks.
You need to specify the actual intermediate table's name in the belongsToMany config, or define the model UserRole. Also, unless your intermediate table has the fields, you'll probably also want to specify timestamps: false as well. So, for example:
Role.belongsToMany(models.User, {
through: 'usr_role',
foreignKey:'role_id',
timestamps: false
});
This will cause sequelize to use that table in the queries it builds without needing a model defined, and will prevent it from requesting the timestamp fields from either the User table or the intermediate.