Sequelize get values from belongsTo relationship - mysql

I am creating an app using an existing database in Mysql.
I can retrieve the values from the tables, but when I try to retrieve the values from associate models, doesn't work.
Purchase Order model:
"use strict";
module.exports = (sequelize, DataTypes) => {
var PurchaseOrder = sequelize.define('purchase_orders' , {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'id'
},
purchaseDate: {
type: DataTypes.DATE,
allowNull: true,
field: 'purchase_date'
},
supplierId: {
type: DataTypes.INTEGER(11),
allowNull: true,
// references: {
// model: 'suppliers',
// key: 'id'
// },
field: 'supplier_id'
},
requestedById: {
type: DataTypes.INTEGER(11),
allowNull: true,
field: 'requested_by_id'
},
masterPurchaseOrderId: {
type: DataTypes.INTEGER(11),
allowNull: true,
// references: {
// model: 'master_purchase_orders',
// key: 'id'
// },
field: 'master_purchase_order_id'
},
createdAt: {
type: DataTypes.DATE,
allowNull: false,
field: 'created_at'
},
updatedAt: {
type: DataTypes.DATE,
allowNull: false,
field: 'updated_at'
}
},{
classMethods:{
associate: (models) => {
PurchaseOrder.belongsTo(models.masterPurchaseOrders,{
foreignkey: 'master_purchase_order_id'
});
},
associate: (models) => {
PurchaseOrder.belongsTo(models.supplier,{
foreignkey: 'supplier_id'
});
},
},
}, {
timestamps: true,
paranoid: false,
underscored: true,
freezeTableName: true,
tableName: 'purchase_orders'
});
return PurchaseOrder;
}
Purchase Order Controller:
"using strict";
const purchaseOrder = require('../models/').purchase_orders;
const Supplier = require('../models/').supplier;
const Master = require('../models/').masterPurchaseOrders;
module.exports= {
index(req, res) {
purchaseOrder
.findAll({
include:[Supplier, Master]
})
.then((masters) => {
res.status(200).json(masters);
})
.catch((error) => {
res.status(500).json(error);
});
},
create(req, res) {
purchaseOrder
.create(req.body)
.then( master => {
res.status(200).json(master);
})
.catch( error => {
res.status(500).json(error);
});
},
};
If I only include the model supplier in the function findall(). I get the data from the purchase and the data from the supplier.
But when I include the model master purchase order. I get an empty json.

Can you do the following
purchaseOrder
.findAll({
include:[{model: Supplier, required:true}, {model: Master, required : false}]
})

It's because you overwrite the associate property of your classMethods, and only the second associate() function will be executed.
You should move both of your association definitions into one function:
classMethods:{
associate: (models) => {
PurchaseOrder.belongsTo(models.masterPurchaseOrders,{
foreignkey: 'master_purchase_order_id'
});
PurchaseOrder.belongsTo(models.supplier,{
foreignkey: 'supplier_id'
});
},
},

Related

Sequelize seems to ignore associations with natural keys and/or adds additional fields

I have 2 situations. The main thing that connects them is that the primary keys on the tables are not autoincrement integers, which seems to cause sequelize to try to create additional association or field names.
Situation 1, I have 2 tables, I have the associations defined. When I try to query it, a random extra field gets inserted, throwing an error.
Model 1 file
const { DataTypes, Model } = require('sequelize');
const modelName = 'BusinessAccountSetting';
const tableName = 'BusinessAccountSettings';
class BusinessAccountSetting extends Model {
static doInit (sequelize) {
this.init({
_id: {
type: DataTypes.BIGINT.UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
BusinessAccountId: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false
},
BusinessSettingKey: {
type: DataTypes.STRING(200),
allowNull: false,
defaultValue: true
},
value: {
type: DataTypes.JSON,
allowNull: false
}
}, {
sequelize,
modelName,
tableName,
timestamps: true,
paranoid: true
});
};
static associate (models) {
this.belongsTo(models.BusinessAccount, {
as: 'business',
foreignKey: 'BusinessAccountId',
targetKey: '_id'
});
this.belongsTo(models.BusinessSetting, {
as: 'setting',
foreignKey: 'BusinessSettingKey',
targetKey: 'BusinessSettingKey'
});
};
};
module.exports = {
modelName,
model: BusinessAccountSetting
};
Model 2 file
const { DataTypes, Model } = require('sequelize');
const modelName = 'BusinessSetting';
const tableName = 'BusinessSettings';
class BusinessSetting extends Model {
static doInit (sequelize) {
this.init({
BusinessSettingKey: {
type: DataTypes.STRING(200),
allowNull: false,
primaryKey: true,
unique: true
},
label: {
type: DataTypes.STRING(200),
allowNull: false
},
description: {
type: DataTypes.STRING(500),
allowNull: true
},
defaultValue: {
type: DataTypes.JSON,
allowNull: false
},
BusinessSettingGroupKey: {
type: DataTypes.STRING(200),
allowNull: false
},
order: {
type: DataTypes.SMALLINT.UNSIGNED,
allowNull: false
}
}, {
sequelize,
modelName,
tableName,
timestamps: true,
paranoid: true
});
};
static associate (models) {
this.belongsTo(models.BusinessSettingGroup, {
as: 'group',
foreignKey: 'BusinessSettingGroupKey',
targetKey: 'BusinessSettingGroupKey'
});
this.hasMany(models.BusinessAccountSetting, {
as: 'businessAccountSettings',
foreignKey: 'BusinessSettingKey',
sourceKey: 'BusinessSettingKey'
});
};
};
module.exports = {
modelName,
model: BusinessSetting
};
When I run this query
const settings = await sqldb.BusinessSetting.findAll({
include: [
{
model: sqldb.BusinessAccountSetting,
as: 'businessAccountSettings',
where: {
BusinessAccountId
},
required: false
}
]
});
It generates this sql
SELECT
`BusinessSetting`.`BusinessSettingKey`,
`BusinessSetting`.`label`,
`BusinessSetting`.`description`,
`BusinessSetting`.`defaultValue`,
`BusinessSetting`.`BusinessSettingGroupKey`,
`BusinessSetting`.`order`,
`BusinessSetting`.`createdAt`,
`BusinessSetting`.`updatedAt`,
`BusinessSetting`.`deletedAt`,
`businessAccountSettings`.`_id` AS `businessAccountSettings._id`,
`businessAccountSettings`.`BusinessAccountId` AS `businessAccountSettings.BusinessAccountId`,
`businessAccountSettings`.`BusinessSettingKey` AS `businessAccountSettings.BusinessSettingKey`,
`businessAccountSettings`.`value` AS `businessAccountSettings.value`,
`businessAccountSettings`.`createdAt` AS `businessAccountSettings.createdAt`,
`businessAccountSettings`.`updatedAt` AS `businessAccountSettings.updatedAt`,
`businessAccountSettings`.`deletedAt` AS `businessAccountSettings.deletedAt`,
`businessAccountSettings`.`BusinessSettingBusinessSettingKey` AS `businessAccountSettings.BusinessSettingBusinessSettingKey`
FROM
`BusinessSettings` AS `BusinessSetting` LEFT OUTER JOIN `BusinessAccountSettings` AS `businessAccountSettings` ON `BusinessSetting`.`BusinessSettingKey` = `businessAccountSettings`.`BusinessSettingKey`
AND (`businessAccountSettings`.`deletedAt` IS NULL AND `businessAccountSettings`.`BusinessAccountId` = 20)
WHERE (`BusinessSetting`.`deletedAt` IS NULL);
Which throws an error because of this:
`businessAccountSettings`.`BusinessSettingBusinessSettingKey` AS `businessAccountSettings.BusinessSettingBusinessSettingKey`
The associations are defined. The primary keys are defined. It should not be trying to add additional fields to fill in the blanks.
It's not an extra hook because it is trying to create a field for the reverse association which is already defined. It's not coming from another model association and I went through all of my files and remove the hooks: true flags just to be sure.
Problem #2, M:N associations with non-numeric keys
File #1
const { DataTypes, Model } = require('sequelize');
const modelName = 'BusinessRoleTemplate';
const tableName = 'BusinessRoleTemplates';
class BusinessRoleTemplate extends Model {
static doInit (sequelize) {
this.init({
BusinessRoleTemplateKey: {
type: DataTypes.STRING(100),
primaryKey: true,
allowNull: false,
unique: true
},
description: {
type: DataTypes.STRING(250),
allowNull: true
},
group: {
type: DataTypes.STRING(50),
allowNull: true
},
isCategoryTemplate: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
ranking: {
type: DataTypes.TINYINT.UNSIGNED,
allowNull: false
},
active: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true
}
}, {
sequelize,
modelName,
tableName,
timestamps: true,
paranoid: true
});
};
static associate (models) {
this.belongsToMany(models.BusinessPermission, {
as: 'permissions',
through: models.BusinessRoleTemplatePermission
});
};
};
module.exports = {
modelName,
model: BusinessRoleTemplate
};
File 2
const { DataTypes, Model } = require('sequelize');
const modelName = 'BusinessPermission';
const tableName = 'BusinessPermissions';
class BusinessPermission extends Model {
static doInit (sequelize) {
this.init({
BusinessPermissionKey: {
type: DataTypes.STRING(100),
allowNull: false,
primaryKey: true,
unique: true
},
plainText: {
type: DataTypes.STRING(100),
allowNull: false
},
description: {
type: DataTypes.STRING(250),
allowNull: true
},
requiresRank: {
type: DataTypes.INTEGER(2).UNSIGNED,
allowNull: false,
defaultValue: 10
},
BusinessPermissionGroupKey: {
type: DataTypes.STRING(100),
allowNull: false
},
isCategoryPermission: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
active: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true
}
}, {
sequelize,
modelName,
tableName,
timestamps: true,
paranoid: true
});
};
static associate (models) {
this.belongsTo(models.BusinessPermissionGroup, {
as: 'group',
foreignKey: 'BusinessPermissionGroupKey',
targetKey: 'BusinessPermissionGroupKey'
});
this.hasMany(models.BusinessPermissionAlternative, {
as: 'alternates',
foreignKey: 'AlternateBusinessPermissionKey',
sourceKey: 'BusinessPermissionKey'
});
this.belongsToMany(models.BusinessRoleTemplate, {
as: 'roleTemplates',
through: models.BusinessRoleTemplatePermission
});
this.belongsToMany(models.BusinessRole, {
as: 'roles',
through: models.BusinessRolePermission
});
};
};
module.exports = {
modelName,
model: BusinessPermission
};
Association table
const { DataTypes, Model } = require('sequelize');
const modelName = 'BusinessRoleTemplatePermission';
const tableName = 'BusinessRoleTemplatePermissions';
class BusinessRoleTemplatePermission extends Model {
static doInit (sequelize) {
this.init({
_id: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
BusinessPermissionKey: {
type: DataTypes.STRING(100),
allowNull: false
},
BusinessRoleTemplateKey: {
type: DataTypes.STRING(100),
allowNull: false
}
}, {
sequelize,
modelName,
tableName,
timestamps: true,
paranoid: false
});
};
static associate (models) {
this.belongsTo(models.BusinessPermission, {
as: 'permission',
foreignKey: 'BusinessPermissionKey',
targetKey: 'BusinessPermissionKey'
});
this.belongsTo(models.BusinessRoleTemplate, {
as: 'role',
foreignKey: 'BusinessRoleTemplateKey',
targetKey: 'BusinessRoleTemplateKey'
});
};
};
module.exports = {
modelName,
model: BusinessRoleTemplatePermission
};
BusinessRoleTemplate hasMany BusinessPermissions through BusinessRoleTemplatePermissions
BusinessRoleTemplatePermissions has the associations for both tables defined, so there shouldn't be a need for anything else.
However, when I run this query:
role = await sqldb.BusinessRoleTemplate.findOne({
where: {
BusinessRoleTemplateKey: data.role
},
attributes: ['BusinessRoleTemplateKey', 'description', 'isCategoryTemplate', 'ranking'],
include: [
{
model: sqldb.BusinessPermission,
as: 'permissions',
attributes: ['BusinessPermissionKey', 'isCategoryPermission']
}
]
});
I get this SQL:
SELECT
`BusinessRoleTemplate`.`BusinessRoleTemplateKey`,
`BusinessRoleTemplate`.`description`,
`BusinessRoleTemplate`.`isCategoryTemplate`,
`BusinessRoleTemplate`.`ranking`,
`permissions`.`BusinessPermissionKey` AS `permissions.BusinessPermissionKey`,
`permissions`.`isCategoryPermission` AS `permissions.isCategoryPermission`,
`permissions->BusinessRoleTemplatePermission`.`_id` AS `permissions.BusinessRoleTemplatePermission._id`,
`permissions->BusinessRoleTemplatePermission`.`BusinessPermissionKey` AS `permissions.BusinessRoleTemplatePermission.BusinessPermissionKey`,
`permissions->BusinessRoleTemplatePermission`.`BusinessRoleTemplateKey` AS `permissions.BusinessRoleTemplatePermission.BusinessRoleTemplateKey`,
`permissions->BusinessRoleTemplatePermission`.`createdAt` AS `permissions.BusinessRoleTemplatePermission.createdAt`,
`permissions->BusinessRoleTemplatePermission`.`updatedAt` AS `permissions.BusinessRoleTemplatePermission.updatedAt`,
`permissions->BusinessRoleTemplatePermission`.`BusinessPermissionBusinessPermissionKey` AS `permissions.BusinessRoleTemplatePermission.BusinessPermissionBusinessPermissionKey`,
`permissions->BusinessRoleTemplatePermission`.`BusinessRoleTemplateBusinessRoleTemplateKey` AS `permissions.BusinessRoleTemplatePermission.BusinessRoleTemplateBusinessRoleTemplateKey`
FROM `BusinessRoleTemplates` AS `BusinessRoleTemplate`
LEFT OUTER JOIN (
`BusinessRoleTemplatePermissions` AS `permissions->BusinessRoleTemplatePermission`
INNER JOIN `BusinessPermissions` AS `permissions`
ON `permissions`.`BusinessPermissionKey` = `permissions->BusinessRoleTemplatePermission`.`BusinessPermissionBusinessPermissionKey`)
ON `BusinessRoleTemplate`.`BusinessRoleTemplateKey` = `permissions->BusinessRoleTemplatePermission`.`BusinessRoleTemplateBusinessRoleTemplateKey`
AND (`permissions`.`deletedAt` IS NULL)
WHERE (`BusinessRoleTemplate`.`deletedAt` IS NULL AND `BusinessRoleTemplate`.`BusinessRoleTemplateKey` = 'Senior Manager');
With all sorts of stuff added:
added fields:
`permissions->BusinessRoleTemplatePermission`.`BusinessPermissionBusinessPermissionKey` AS `permissions.BusinessRoleTemplatePermission.BusinessPermissionBusinessPermissionKey`,
`permissions->BusinessRoleTemplatePermission`.`BusinessRoleTemplateBusinessRoleTemplateKey` AS `permissions.BusinessRoleTemplatePermission.BusinessRoleTemplateBusinessRoleTemplateKey`
Added associations:
ON `permissions`.`BusinessPermissionKey` = `permissions->BusinessRoleTemplatePermission`.`BusinessPermissionBusinessPermissionKey`)
If I change the association in BusinessRoleTemplate to this, it works:
this.belongsToMany(models.BusinessPermission, {
as: 'permissions',
through: models.BusinessRoleTemplatePermission,
foreignKey: 'BusinessRoleTemplateKey',
otherKey: 'BusinessPermissionKey'
});
I shouldn't need to add the foreignKey and otherKey because the associations are already defined in the through table, but sequelize isn't recognizing them, it is trying to create them.

this.sequelize.isDefined Node Modules?

I'm trying to seed into a database. I have successfully seeded using 2 other models, but when I try to seed data into a Model called 'Comment', I get this error:
TypeError: this.sequelize.isDefined is not a function
It has only happened for this particular model, even though the syntax is practically identical to the other two. Has anyone gotten this error before?
Here is the seed.js file. I commented out the Comment section (the one that doesn't work) but the other two are just fine.
const sequelize = require('../config/connection');
const { User, Post, Comment } = require('../models');
const userData = require('./usersSeed.json');
const postData = require('./postsSeed.json');
const commentData = require('./commentSeed.json')
const seedDatabase = async () => {
await sequelize.sync({ force: true });
await User.bulkCreate(userData, {
individualHooks: true,
returning: true,
});
await Post.bulkCreate(postData, {
individualHooks: true,
returning: true,
});
/* await Comment.bulkCreate(commentData,
{
individualHooks: true,
returning: true,
}); */
process.exit(0);
};
seedDatabase();
Here is a model that works fine
const { Model, DataTypes } = require('sequelize');
const sequelize = require('../config/connection');
class Post extends Model {}
Post.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
},
post_title: {
type: DataTypes.TEXT,
allowNull: false
},
post_text: {
type: DataTypes.TEXT,
allowNull: true,
},
user_id: {
type: DataTypes.INTEGER,
references: {
model: 'user',
key: 'id'
}
},
date_posted: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
}
},
{
sequelize,
timestamps: false,
freezeTableName: true,
underscored: true,
modelName: 'post',
}
)
module.exports = Post;
Here is the Comment model
const { Model, DataTypes } = require('sequelize');
const sequelize = require('sequelize');
class Comment extends Model {}
Comment.init(
{
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
comment_text: {
type: DataTypes.TEXT,
allowNull: false
},
post_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'post',
key: 'id'
}
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'user',
key: 'id'
}
}
},
{
sequelize,
timestamps: false,
freezeTableName: true,
underscored: false,
modelName: 'comment'
}
)
module.exports = Comment;
Here is the index for the Models
const User = require('./User');
const Post = require('./Post');
const Comment = require('./Comment')
User.hasMany(Post, {
foreignKey: 'user_id'
});
Post.belongsTo(User, {
foreignKey: 'user_id',
});
Comment.belongsTo(User, {
foreignKey: 'user_id'
});
Comment.belongsTo(Post, {
foreignKey: 'post_id'
});
User.hasMany(Comment, {
foreignKey: 'user_id'
});
Post.hasMany(Comment, {
foreignKey: 'post_id'
});
module.exports = { User, Post, Comment};
Wow so dumb. I needed to change the sequelize variable to require the connection
const sequelize = require('../config/connection');

SequelizeEagerLoadingError: product is not associated to collection

I use sequelize ORM in Mysql. I have 3 Models: Product, Collection, CollectionProduct
relationship between Product and Collection are many to many and for handle this in sequelize i used belongsToMany association. every thing is Ok but when i run this code to get a collection with its products with include Eager this error occure:
SequelizeEagerLoadingError: product is not associated to collection!
Product Model:
module.exports = (sequelize, Sequelize) => {
const Product = sequelize.define('product', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
name_en: {
type: Sequelize.STRING(255),
},
description_en: {
type: Sequelize.STRING(1024),
},
price: {
type: Sequelize.FLOAT,
allowNull: false,
},
type: {
type: Sequelize.STRING(255),
},
height: {
type: Sequelize.INTEGER,
},
width: {
type: Sequelize.INTEGER,
},
createdAt: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
allowNull: false,
},
updatedAt: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
allowNull: false,
},
}, {})
Product.associate = (models) => {
Product.belongsToMany(models.collection, { through: models.collectionProduct, as: 'collections', foreignKey: 'productId' })
}
return Product
}
Collection Model :
module.exports = (sequelize, Sequelize) => {
const Collection = sequelize.define(
'collection', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
autoIncrement: true,
},
name_en: {
type: Sequelize.STRING(255),
},
itemsCount: {
type: Sequelize.INTEGER,
},
createdAt: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
allowNull: false,
},
updatedAt: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
allowNull: false,
},
}, {},
)
Collection.associate = (models) => {
Collection.belongsToMany(models.product, { through: models.collectionProduct, as: 'products', foreignKey: 'collectionId' })
}
return Collection
}
CollectionProduct Model:
module.exports = (sequelize, Sequelize) => {
const CollectionProduct = sequelize.define('collectionProduct', {
collectionId: {
type: Sequelize.INTEGER,
},
productId: {
type: Sequelize.INTEGER,
},
createdAt: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
allowNull: false,
},
updatedAt: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
allowNull: false,
},
}, {})
CollectionProduct.associate = (models) => {}
return CollectionProduct
}
routes/collection.js
const express = require('express')
const router = express.Router()
const Collection = require('../../controllers/collectionController')
router.get('/:id', async (req, res) => {
const { id: collectionId } = req.params
const collection = await Collection.getOne(collectionId)
return collection
}
collectionController
const db = require('../models/index')
const Collection = db.collection
const Product = db.product
const getOne = async (collectionId) => {
const collection = await Collection.findByPk(collectionId, {
include: {
model: Product,
as: 'products',
attributes: ['id', 'name_en'],
},
})
return collection
}
I found my problem. in collectionController i used model: Product
and Product should be a sequelize model. but in my code this is a function that have been called in models/index. so i changed my calling and pass a sequelize model to getOne

sequelize many to many not working correcttly with a legacy databse

I've got an existing mysql database where i've got the following tables : category,product and product_category.I've used sequelizer-auto package to generate models from the 3 tables like the following:
Product.js ,model generated from product table:
module.exports = function(sequelize, DataTypes) {
const Product= sequelize.define('product', {
productId: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'product_id'
},
name: {
type: DataTypes.STRING(100),
allowNull: false,
field: 'name'
},
description: {
type: DataTypes.STRING(1000),
allowNull: false,
field: 'description'
},
price: {
type: DataTypes.DECIMAL,
allowNull: false,
field: 'price'
},
discountedPrice: {
type: DataTypes.DECIMAL,
allowNull: false,
defaultValue: '0.00',
field: 'discounted_price'
},
image: {
type: DataTypes.STRING(150),
allowNull: true,
field: 'image'
},
image2: {
type: DataTypes.STRING(150),
allowNull: true,
field: 'image_2'
},
thumbnail: {
type: DataTypes.STRING(150),
allowNull: true,
field: 'thumbnail'
},
display: {
type: DataTypes.INTEGER(6),
allowNull: false,
defaultValue: '0',
field: 'display'
}
}, {
tableName: 'product'
});
Product.associate=(models)=>{
Product.belongsToMany(models.category,{
through:'product_category',
foreignkey:'product_id',
as:'categories'
})
}
return Product;
};
Category.js generated from 'category table'
module.exports = function(sequelize, DataTypes) {
const Category= sequelize.define('category', {
categoryId: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'category_id'
},
departmentId: {
type: DataTypes.INTEGER(11),
allowNull: false,
field: 'department_id'
},
name: {
type: DataTypes.STRING(100),
allowNull: false,
field: 'name'
},
description: {
type: DataTypes.STRING(1000),
allowNull: true,
field: 'description'
}
},
{
tableName: 'category',
});
Category.associate=(models)=>{
Category.belongsToMany(models.Product, {
through: 'product_category',
foreignkey: 'category_id',
as: 'products'
});
}
return Category;
};
ProductCategory from product_category table
module.exports = function(sequelize, DataTypes) {
return sequelize.define('product_category', {
productId: {
type: DataTypes.INTEGER(11),
references:{
key:'product_id',
model:'product'
}
},
categoryId: {
type: DataTypes.INTEGER(11),
references:{
key: 'category_id',
model:'category'
}
}
}, {
tableName: 'product_category'
});
};
And here is the category controller categories.js:
const db=require('../services/db_init');
const DataTypes=require('sequelize').DataTypes;
const Category=require('../database/models/Category')(db,DataTypes);
const Product=require('../database/models/Product')(db,DataTypes);
const {category_errors:{cat_01,cat_02}} = require('../services/errors.js');
//test code
const Product = require('../database/models/Product')(db,DataTypes);
module.exports=(app)=>{
app.get('/categories',async(req,res)=>{
try {
const categories = await Category.findAll({
include:{
model:Product,
as:'products'
}
});
return res.send(categories).status(200);
} catch (err) {
return res.json({error:err}).status(400);
}
});
app.get('/categories/:id',async(req,res)=>{
const id=req.params.id;
//checking if the id is a number
if(isNaN(id)){
return res.json({error:cat_01})//error returned
}
try {
const category=await Category.findByPk(id);
if(category){
return res.send(category).status(200);
}
return res.json({error:cat_02}).status(404);
} catch (err) {
return res.json(err).status(400);
}
});
}
All methode are working as expected,but after adding relashionship between models i've got some problems.First in GET /categories ,the implementation of the query was const categories = await Category.findAll() and everything was working fine,but after changing the implementation to const categories = await Category.findAll({include:{model:Product,as:'products'}}); i get the follwing error {
"error": {
"name": "SequelizeEagerLoadingError"
}
}
I've tried to read many topics,and solutions but i always have the same issue

Error retrieving values from sequelize association

I need to retrieve the values from two associated models from an existing database.
Model Master
"use strict";
module.exports = (sequelize, DataTypes) => {
var MasterPurchaseOrder = sequelize.define('master_purchase_order' , {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'id'
},
requestedById: {
type: DataTypes.INTEGER(11),
allowNull: true,
field: 'requested_by_id'
},
status: {
type: DataTypes.STRING,
allowNull: true,
field: 'status'
}
},{
classMethods:{
associate: (models) =>{
MasterPurchaseOrder.hasMany(models.purchase_order,{
as: 'purchase_order',
foreignkey: 'master_purchase_order_id'
});
},
},
}, {
timestamps: true,
paranoid: false,
underscored: true,
freezeTableName: true,
tableName: 'master_purchase_orders'
});
return MasterPurchaseOrder;
}
Purchase Order Model
"use strict";
module.exports = (sequelize, DataTypes) => {
var PurchaseOrder = sequelize.define('purchase_order' , {
id: {
type: DataTypes.INTEGER(11),
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: 'id'
},
purchaseDate: {
type: DataTypes.DATE,
allowNull: true,
field: 'purchase_date'
},
requestedById: {
type: DataTypes.INTEGER(11),
allowNull: true,
field: 'requested_by_id'
},
masterPurchaseOrderId: {
type: DataTypes.INTEGER(11),
allowNull: true,
field: 'master_purchase_order_id'
}
},{
classMethods:{
associate: (models) => {
PurchaseOrder.belongsTo(models.master_purchase_order,{
as: 'master_purchase_order',
foreignkey: 'master_purchase_order_id'
});
},
},
}, {
timestamps: true,
paranoid: false,
underscored: true,
freezeTableName: true,
tableName: 'purchase_orders'
});
return PurchaseOrder;
}
This is my purchase order controller:
"using strict";
const purchaseOrder = require('../models/').purchase_order;
const MasterPurchaseOrder = require('../models/').master_purchase_order;
module.exports= {
index(req, res) {
purchaseOrder
.findAll({
include:[
{model: MasterPurchaseOrder, as: 'master_purchase_order'}
]
})
.then((masters) => {
res.status(200).json(masters);
});
// .catch((error) => {
// res.status(500).json(error);
// });
},
};
I get the error:
Unhandled rejection Error: master_purchase_order
(master_purchase_order) is not associated to purchase_order!
Any advice
I was overriding the classMethods definition in my child-model.
{
classMethods:{
associate: (models) => {
PurchaseOrder.belongsTo(models.master_purchase_order,{
as: 'master_purchase_order',
foreignkey: 'master_purchase_order_id'
});
associate: (models) => {
PurchaseOrder.belongsTo(models.suuplier,{
as: 'supplier',
foreignkey: 'supplier_id'
});
},
},
}
The right way is:
{
classMethods:{
associate: (models) => {
PurchaseOrder.belongsTo(models.master_purchase_order,{
as: 'master_purchase_order',
foreignkey: 'master_purchase_order_id'
});
PurchaseOrder.belongsTo(models.suuplier,{
as: 'supplier',
foreignkey: 'supplier_id'
});
},
}