SequelizeEagerLoadingError : associated not working in sequelize - mysql

I have two tables , Parent table is checkout_product and it's child table is product_attributes
Now I am creating association between two tables so it's getting error:
Here is my code
const Sequelize = require('sequelize');
const { checkout_product_view } = require('../controller/checkoutProductController');
const sequelize = new Sequelize('celeb', 'root', '', {
host: 'localhost',
dialect: 'mysql' ,
});
var Checkout_product = sequelize.define('checkout_products',{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: Sequelize.STRING
},
price : {
type : Sequelize.STRING
},
image : {
type: Sequelize.STRING
},
quantity : {
type: Sequelize.STRING
},
});
Checkout_product.associate = function(models) {
checkout_products.hasMany(models.Product_attributes, {
foreignKey: 'product_id',
});
};
sequelize.sync()
.catch(error => console.log('This error occured', error));
module.exports = Checkout_product;
And here is my product_attributes model:
const Sequelize = require('sequelize');
const sequelize = new Sequelize('celeb', 'root', '', {
host: 'localhost',
dialect: 'mysql' ,
});
var Product_attribute = sequelize.define('product_attribute',{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
product_id: {
type: Sequelize.INTEGER
},
attribute_name : {
type : Sequelize.STRING
},
attribute : {
type : Sequelize.STRING
},
price : {
type : Sequelize.STRING
}
});
Product_attribute.associate = (models) => {
Product_attribute.belongsTo(models.Checkout_product, {
foreign_key: 'product_id',
sourceKey: 'id'
});
};
sequelize.sync()
.then(() => console.log('Product_attribute'))
.catch(error => console.log('This error occured', error));
module.exports = Product_attribute;
Product has many product_attributes so whenever I called following function getting this error :
module.exports.checkout_product_get = function (req, res) {
Checkout_product.findAll({
include: [ {
model : Product_attributes
}]
})
.then(checkout_product => {
console.log(checkout_product),
res.json(checkout_product)
})
}
Error : UnhandledPromiseRejectionWarning: SequelizeEagerLoadingError: product_attribute is not associated to checkout_products!

You didn't call associate methods for all registered models.
I recommend you to define and register all models and associations like I described in this answer

Related

Graphql using Sequelize + mysql: Database Variable always empty

I have gone through many different solutions to overcome this problem. But nothing seems to be working.
My Files:
database.js
const {Sequelize} = require("sequelize");
var db = {}
const sequelize = new Sequelize('ETconnect', 'root', 'D5kIzmJB', {
host: '10.10.10.11',
port: '3306',
dialect: 'mysql',
define: {
freezeTableName: true,
},
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000,
},
// <http://docs.sequelizejs.com/manual/tutorial/querying.html#operators>
operatorsAliases: false,
})
let models = [
require('./models/users.js'),
]
// Initialize models
models.forEach(model => {
const seqModel = model(sequelize, Sequelize)
db[seqModel.name] = seqModel
})
// Apply associations
Object.keys(db).forEach(key => {
if ('associate' in db[key]) {
db[key].associate(db)
}
})
db.sequelize = sequelize
db.Sequelize = Sequelize
exports.db;
models/users.js
const {Sequelize} = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('users', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
primaryKey: true
},
name: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(50),
allowNull: false,
unique: "email"
},
password: {
type: DataTypes.STRING(255),
allowNull: false
},
profileimage: {
type: DataTypes.STRING(45),
allowNull: true
}
}, {
sequelize,
tableName: 'users',
timestamps: false,
indexes: [
{
name: "PRIMARY",
unique: true,
using: "BTREE",
fields: [
{ name: "id" },
]
},
{
name: "email",
unique: true,
using: "BTREE",
fields: [
{ name: "email" },
]
},
]
});
};
models/init-models.js
var DataTypes = require("sequelize").DataTypes;
var _users = require("./users");
function initModels(sequelize) {
var users = _users(sequelize, DataTypes);
return {
users,
};
}
module.exports = initModels;
module.exports.initModels = initModels;
module.exports.default = initModels;
Graphql/users.js
const {gql} = require("apollo-server-express");
const db = require("../database");
//import { gql } from 'apollo-server-express'
//import * as db from '../database'
exports.typeDefs = gql`
extend type Query {
users: [User]
user(id: ID!): User
}
type User {
id: ID!
name: String
email: String
}
`
exports.resolvers = {
Query: {
users: async () => console.log(db),
user: async (obj, args, context, info) =>
db.users.findByPk(args.id),
},
}
Everytime I use the users query in the Apollo test environment I get a log which says that the Database variable is empty.
Output: {}
Can anybody tell me what I did wrong? Does it not connect to the Database? Because we have a similar application that does perfectly fine.
I would really appreciate the help.

Sequelize include options cannot get another models

I have two model that are belongs to each other (order_items.js & products.js) productId as a foreign key in order_items, code as below:
order_items.js
const { DataTypes } = require('sequelize')
const db_config = require(`../config/config`)
const Product = require('./product')
const OrderItem = db_config.define('order_item', {
productId : { type: DataTypes.INTEGER, allowNull:false, references: {model: Product, key: 'id'} },
quantity: { type: DataTypes.INTEGER }
}, {
freezeTableName: true
})
module.exports = OrderItem
product.js
const { DataTypes } = require('sequelize')
const db_config = require(`../config/config`)
const Category = require('./category')
const Product = db_config.define('product', {
productName : { type: DataTypes.STRING, allowNull:false },
productPrice: { type: DataTypes.INTEGER, allowNull:false },
productDescription: { type: DataTypes.STRING, allowNull:true },
productImage: { type: DataTypes.STRING, allowNull:true },
productStock: { type: DataTypes.INTEGER, validate: { min: 0 }, defaultValue: 0, allowNull: false },
CategoryId: { type: DataTypes.INTEGER, allowNull:false, defaultValue: 1, references: {model: Category, key: 'id'}}
}, {
freezeTableName: true
})
module.exports = Product
order_routes.js
router.get('/', async (req, res) => {
try {
const dataList = await OrderItem.findAll({include: [{model:Product, required:true}]})
res.send({
status: "success",
message: "data found",
data: dataList
})
} catch (err) {
res.send({
status: "failed",
message: err})
}
})
Result in postman
Can anyone help please? what I'm trying to do is that when I get the order_item, it also get the products refers to the id of the products
Where are the associations in the model definition? I see a reference on column field but you also needs to do below definitions seperately
Inside OrderItem Model File
OrderItem.associate = models => {
OrderItem.belongsTo(Product, {as: "product", foreignKey: "productId", sourceKey: "id"});
};
Inside Products Model File
Product.associate = models => {
Product.hasMany(OrderItem, {as: "orders", foreignKey: "productId", sourceKey: "id"});
};
Also I would suggest you to store price in OrderItem collection as well so in case in future when the product price changes your past order data is not incorrect.

Sequelize Error: you must use the 'as' keyword to specify the alias of the association you want to include. - node.js

I am making a web application which is similar to 'Twitter'.
When I ran the server,
'user is associated to user multiple times. To identify the correct association,
You must use the 'as' keyword to specify the alias of the association you want to include.'
<- this message appeared.
I applied 'as' keyword for the relationship between 'followers' and 'followings'.
but the error message kept on appearing.
I'm sure that I did something wrong in someway, but I can't figure out what exactly it is.
can somebody help me?
models/index.js
'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.User = require('./user')(sequelize, Sequelize);
db.Post = require('./post')(sequelize, Sequelize);
db.Hashtag = require('./hashtag')(sequelize, Sequelize);
db.User.hasMany(db.Post); //1 : n
db.Post.belongsTo(db.User);
// m: n
db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag' });
db.Hashtag.belongsToMany(db.Post, { through: 'PostHashtag' });
// I use alias here *****
db.User.belongsToMany(db.User, {
foreignKey: 'followingId',
as: 'Followers',
through: 'Follow',
});
db.User.belongsToMany(db.User, {
foreignKey: 'followerId',
as: 'Followings',
through: 'Follow',
});
module.exports = db;
models/user.js
module.exports = (sequelize, DataTypes) => (
sequelize.define('user', {
email: {
type: DataTypes.STRING(40),
allowNull: true,
unique: true,
},
nick: {
type: DataTypes.STRING(15),
allowNull: false,
},
password: {
type: DataTypes.STRING(100),
allowNull: true,
},
provider: {
type: DataTypes.STRING(10),
allowNull: false,
defaultValue: 'local',
},
snsId: {
type: DataTypes.STRING(30),
allowNull: true,
},
}, {
timestamps: true,
paranoid: true,
})
);
models/post.js
module.exports = (sequelize, DataTypes) => (
sequelize.define('user', {
email: {
type: DataTypes.STRING(40),
allowNull: true,
unique: true,
},
nick: {
type: DataTypes.STRING(15),
allowNull: false,
},
password: {
type: DataTypes.STRING(100),
allowNull: true,
},
provider: {
type: DataTypes.STRING(10),
allowNull: false,
defaultValue: 'local',
},
snsId: {
type: DataTypes.STRING(30),
allowNull: true,
},
}, {
timestamps: true,
paranoid: true,
})
);
models/hashtag.js
module.exports = (sequelize, DataTypes) => (
sequelize.define('hashtag', {
title: {
type: DataTypes.STRING(15),
allowNull: false,
unique: true,
},
}, {
timestamps: true,
paranoid: true,
})
);
I think this will solve your problem you have to create a table follower than associate it with user table with following and follower alias and use it to query follower and following
follower Model
module.exports = (sequelize, datatypes) => {
sequelize.define('follower', {
_id: {
type: datatypes.integer,
allownull: false,
primarykey: true,
autoincrement: true
},
userid: {
type: datatypes.integer,
allownull: false
},
followingid: {
type: datatypes.integer,
allownull: false
}
});
}
association
db.follower.belongsTo(db.user, {
as: 'following',
foreignkey: 'followingid'
});
db.follower.belongsto(db.user, {
as: 'follower',
foreignkey: 'userid'
});
query to get follower
follower.findall({
where: {
followingid: userid
},
attributes: ['_id'],
include: [{
model: user, attributes:
['fullname', 'username', '_id', 'picture'],
as: 'follower'
}]
})

Node Js (Sequelize) - Unhandled rejection SequelizeDatabaseError: Unknown column 'id' in 'field list'

I try to get two column values from my mysql database.
This is my model
const Sequelize = require('sequelize');
const db = require('../config/database');
const AuthDetails = db.define('auth_details', {
client_id : {
type: Sequelize.STRING
},
client_secret : {
type: Sequelize.STRING
}
},{
timestamps : false
});
module.exports = AuthDetails;
And, This is my route
router.post('/login', (req, res, next) => {
// console.log(req.body);
Users.findOne( { where : { mobile_number: req.body.mobile_number}})
.then(users => {
UserAuthDet.findAll({
where: {
client_id: req.body.client_id,
client_secret: req.body.client_secret
}
});
});
I'm having the error, while getting the client_id and client_secret from the database.
My error
UPDATED : Database.js File
const Sequelize = require('sequelize');
module.exports = new Sequelize('mydbname', 'root', '', {
host: 'localhost',
dialect: 'mysql',
operatorsAliases: false,
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
},
});
Try adding primaryKey: true to client_id in AuthDetails.
const AuthDetails = db.define('auth_details', {
client_id : {
type: Sequelize.STRING,
primaryKey: true
},
client_secret : {
type: Sequelize.STRING
}
},{
timestamps : false
});
I am guessing Sequelize considers id as primary key by default unless it is specified and appending id to findAll query.
ref: https://github.com/sequelize/sequelize/issues/741

Sequelize Relation with mysql does not perform correct query

I'm trying to do an association in sequelize with mysql, but i dont't have the expected result
This my user model:
const bcrypt = require('bcrypt');
module.exports = (sequelize, DataTypes) => {
const user = sequelize.define('user', {
displayName: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
active: DataTypes.BOOLEAN,
description: DataTypes.STRING,
password: {
type: DataTypes.STRING,
allowNull: false
},
gender: DataTypes.CHAR(1),
presentationSentence: DataTypes.STRING,
hairId: DataTypes.INTEGER,
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE,
}, {
hooks: {
beforeCreate: user => {
const salt = bcrypt.genSaltSync();
user.password = bcrypt.hashSync(user.password, salt);
}
},
isValidPassword: (password, salt) => {
return bcrypt.compareSync(password, salt);
}
});
user.associate = models => {
user.hasOne(models.hair, {
foreignKey: 'id',
sourceKey: 'hairId'
});
user.hasMany(models.photo, {
foreignKey: 'userId'
});
};
return user;
};
And i have a hair model:
module.exports = (sequelize, DataTypes) => {
const hair = sequelize.define('hair', {
type: DataTypes.ENUM('Liso', 'Crespo', 'Ondulado', 'Cacheado', 'Calvo')
});
return hair;
};
The problem is, that when i perform the query, it looks for hair model with user id, not hairId field;
SELECT `user`.`id`, `user`.`displayName`, `user`.`email`, `user`.`active`, `user`.`description`, `user`.`password`, `user`.`gender`, `user`.`presentationSentence`, `user`.`hairId`, `user`.`createdAt`, `user`.`updatedAt`, `hair`.`id` AS `hair.id`, `hair`.`type` AS `hair.type`, `hair`.`createdAt` AS `hair.createdAt`, `hair`.`updatedAt` AS `hair.updatedAt`, `photos`.`id` AS `photos.id`, `photos`.`url` AS `photos.url`, `photos`.`active` AS `photos.active`, `photos`.`avatar` AS `photos.avatar`, `photos`.`userId` AS `photos.userId`, `photos`.`createdAt` AS `photos.createdAt`, `photos`.`updatedAt` AS `photos.updatedAt` FROM `users` AS `user` LEFT OUTER JOIN `hairs` AS `hair` ON `user`.`id` = `hair`.`id` LEFT OUTER JOIN `photos` AS `photos` ON `user`.`id` = `photos`.`userId`;
so, it always bring me the hair field with the id 1
Does anyone know why this is happening?
I spend so many hours with this issue and i cannot evolve to a solution
Your hair model definition is wrong, give it an auto-increment primary key and a enum value.
module.exports = (sequelize, DataTypes) => {
const hair = sequelize.define('hair', {
hair_id: {
type: DataTypes.BIGINT.UNSIGNED,
autoIncrement: true,
primaryKey: true,
},
email: {
type: DataTypes.STRING,
references: {
model: 'Users',
key: 'email',
}
}
hair_type: {
type: DataTypes.ENUM,
values: [
'Liso',
'Crespo',
'Ondulado',
'Cacheado',
'Calvo'
],
defaultValue: 'Liso',
notNull: true
}
});
return hair;
};
And in the associations,
user.associate = models => {
user.hasOne(models.hair, {
foreignKey: 'email',
sourceKey: 'email'
});
user.hasMany(models.photo, {
foreignKey: 'userId'
});
};