Making relation one to many on sequelize node js - node.js

I've been tried of making relation of one to many on sequelize, i just wanna make the "jadwal" data have data of "dosen".
This's the JadwalModel that have the foreignKey
// Main Folder > models > JadwalModel.js
import { Sequelize } from "sequelize";
import db from "../config/Database.js";
import Dosen from "./DosenModel.js";
const { DataTypes } = Sequelize;
const Jadwal = db.define('jadwal', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
id_dosen: {
type: DataTypes.INTEGER
},
room: {
type: DataTypes.STRING
},
date: {
type: DataTypes.DATE
}
}, {
freezeTableName: true
});
// Dosen.hasMany(Jadwal, { foreignKey: 'id_dosen' });
// Jadwal.belongsTo(Dosen, { foreignKey: 'id_dosen' }); // This return ReferenceError: Cannot access 'Dosen' before initialization
export default Jadwal;
This's the Dosen model that the primaryKey/ ReferenceKey
// Main Folder > models > DosenModel.js
import { Sequelize } from "sequelize";
import db from '../config/Database.js';
import Jadwal from "./JadwalModel.js";
const { DataTypes } = Sequelize;
const Dosen = db.define('dosen', {
id_dosen: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
id_matkul: {
type: DataTypes.INTEGER
},
id_user: {
type: DataTypes.INTEGER,
},
name: {
type: DataTypes.STRING
},
nip: {
type: DataTypes.INTEGER
},
username: {
type: DataTypes.STRING
},
password: {
type: DataTypes.STRING
},
refresh_token: {
type: DataTypes.TEXT
}
}, {
freezeTableName: true
});
// Dosen.hasMany(Jadwal, { foreignKey: 'id_dosen' });
// Jadwal.belongsTo(Dosen, { foreignKey: 'id_dosen' });
export default Dosen;
This's the jadwal controller the file to get the data
// Main Folder > controllers > Jadwal.js
import Dosen from '../models/DosenModel.js';
import Jadwal from '../models/JadwalModel.js';
export const getJadwals = async(req, res) => {
try {
const jadwal = await Jadwal.findAll({
attributes: ['id', 'id_dosen', 'room', 'date']
}, {
include: [{ model: Dosen }]
});
res.status(200).json(jadwal);
} catch (error) {
console.log(error);
}
}
And this's the example result
// Result
[
{
"id": 1,
"id_dosen": 1,
"room": "Ruang TR 2",
"date": "2022-05-26T10:00:00.000Z"
}
]
// The result that i want is
[
{
"id": 1,
"dosen": {
"name" : "dosenName"
},
"room": "Ruang TR 2",
"date": "2022-05-26T10:00:00.000Z"
}
]

That wasn't error, i just forgot because i only fetch several field not all so i decide to delete the attributes and get the data relation
attributes: ['id', 'id_dosen', 'ruangan', 'tanggal']

Related

can not get userID in sequelize?

this is user model
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class User 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({ Kyc }) {
// define association here
this.hasOne(Kyc, { foreignKey: "userID" });
}
}
User.init(
{
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
},
firstname: {
type: DataTypes.STRING,
allowNull: false,
},
lastname: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
role: {
type: DataTypes.STRING,
defaultValue: "user",
allowNull: false,
validate: {
roles(value) {
const rolesArray = ["user", "admin"];
if (!rolesArray.includes(value)) {
throw new Error('plese enter valid role "user or admin"');
}
},
},
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
modelName: "User",
}
);
return User;
};
this is kyc model
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class Kyc 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({ User }) {
// define association here
this.belongsTo(User, { foreignKey: "userID", as: "user" });
}
}
Kyc.init(
{
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
},
docimg: {
type: DataTypes.STRING,
allowNull: false,
},
details: {
type: DataTypes.STRING,
allowNull: false,
},
status: {
type: DataTypes.STRING,
allowNull: false,
},
userID: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
{
sequelize,
modelName: "Kyc",
}
);
return Kyc;
};
kyc middlware
const verifyKyc = async (req, res, next) => {
// check that user has posted or not if yes then give error
const user = await User.findByPk(req.user.id);
const kyc = await Kyc.findOne({
userID: req.user.id,
});
console.log(user.id);
console.log(kyc);
if (user.id === kyc) {
}
next();
};
Error
Executing (default): SELECT "id", "uuid", "firstname", "lastname", "email", "role", "password", "createdAt", "updatedAt" FROM "Users" AS "User" WHERE "User"."id" = 1;
(sequelize) Warning: Model attributes (userID) passed into finder method options of model Kyc, but the options.where object is empty. Did you forget to use options.where?
Executing (default): SELECT "id", "uuid", "docimg", "details", "status", "userID", "createdAt", "updatedAt" FROM "Kycs" AS "Kyc" LIMIT 1;
1
Kyc {
dataValues: {
id: 117,
uuid: '99461f78-4781-42cc-a01f-b6541fda849d',
docimg: 'admin.png',
details: 'KSAPK0550P',
status: 'pending',
userID: 1,
createdAt: 2022-06-04T10:59:21.039Z,
updatedAt: 2022-06-04T10:59:21.039Z
_previousDataValues: {
id: 117,
uuid: '99461f78-4781-42cc-a01f-b6541fda849d',
docimg: 'admin.png',
details: 'KSAPK0550P',
status: 'pending',
userID: 1,
createdAt: 2022-06-04T10:59:21.039Z,
updatedAt: 2022-06-04T10:59:21.039Z
isNewRecord: false
}
i am tring to print userID but giving me this error
thank you for your help
You forgot to wrap your condition into where option:
const kyc = await Kyc.findOne({
where: {
userID: req.user.id,
}
});

Sequelize association table group

I have two tables medforms and category each medform can have multiple categories. for multiple categories, I made another association table medform_categories.
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class MedForm 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
}
};
MedForm.init({
med_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
med_name: {
type: DataTypes.STRING,
allowNull: false
},
}, {
sequelize,
modelName: 'medforms',
});
MedForm.associate = function (models) {
MedForm.hasMany(models.medforms_category, {
foreignKey: 'med_id',
as: 'medform'
});
};
return MedForm;
};
category table schema:
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Category extends Model {
static associate(models) {
}
};
Category.init({
category_id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
category_name: {
type: DataTypes.STRING,
},
}, {
sequelize,
modelName: 'categories',
});
Category.associate = function (models) {
Category.hasMany(models.medforms_category, {
foreignKey: 'category_id',
as: 'category'
});
};
return Category;
};
and finally the association table medform_category
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Medform_categories extends Model {
static associate(models) {
}
};
Medform_categories.init({
medform_category_id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
category_id: {
type: DataTypes.INTEGER,
references: {
model: 'categories',
key: 'category_id'
},
onUpdate: 'CASCADE',
onDelete: 'CASCADE'
},
med_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'medforms',
key: 'med_id'
},
onUpdate: 'CASCADE',
onDelete: 'CASCADE'
},
}, {
sequelize,
modelName: 'medform_categories',
});
Medform_categories.associate = function (models) {
Medform_categories.belongsTo(models.medforms, {
foreignKey: 'med_id',
as: 'medform'
});
Medform_categories.belongsTo(models.categories, {
foreignKey: 'category_id',
as: 'category'
});
};
return Medform_categories;
};
now I want data like:
"category": [
{
"category_id": 1,
"category_name": "cat1",
"medforms": {
"med_id": 1,
"med_name": "Mobilfunk 1",
"med_fullname": "Mobilfunk 1",
},
{
"med_id": 2,
"med_name": "Mobilfunk 2",
"med_fullname": "Mobilfunk 2",
}
},
{
"category_id": 2,
"category_name": "cat2",
"medforms": {
"med_id": 1,
"med_name": "Mobilfunk 1",
"med_fullname": "Mobilfunk 1",
},
{
"med_id": 3,
"med_name": "Mobilfunk 3",
"med_fullname": "Mobilfunk 3",
}
},
]
can some one please help me here? what I should do here? Inside the
controller to fetch data like mentioned above?
const db = require("../models");
const Categories = db.categories; // tables db instance
// Retrieve all objects (with include)
exports.getAllCategories = (req, res) => {
Categories.findAll({
include: [
{
model: db.medforms_category,
as: 'category',
include: [
{
model: db.medforms,
as: 'medform',
}]
},
],
})
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while retrieving all data."
});
});
};
If you have a N:N relation, you not necessarely need to have a Model to represent this table.
// Medforms
// ...
static associate(models) {
this.belongsToMany(models.categories, { through: 'medform_categories' });
}
// Categories
// ...
static associate(models) {
this.belongsToMany(models.medforms, { through: 'medform_categories' });
}
// Query will be something like
const categories = await Categories.findAll({
where: {...},
include: ['medforms']
})
const medforms = await Medforms.findAll({
where: {...},
include: ['categories']
})

Return only desired columns from Sequelize.js with join

I am switching from using node-mssql to Sequelize in order to access my database in a simpler fashion. As a newbie to sequelize I am stumbling my way through pulling the correct data.
As I am converting a .net site with .net authentication to a node site I am using the existing authentication database. Currently I am trying to pull all roles for an existing user.
Here is the code I have so far. It returns both userID and roleID along with the username and role name that I desire. How can I remove these 2 ID columns from my query results?
test.aspnet_Users.findAll({
logging: console.log,
where: { LoweredUserName: `mcad2\\${user}` },
attributes: ['LoweredUserName'],
include: {
model: test.aspnet_Roles,
as: 'RoleId_aspnet_Roles',
attributes: ['LoweredRoleName']
}
}).then(user => {
console.log('\n\n' + JSON.stringify(user))
})
The database is set up so that both userID and roleID are contained in a third table, aspnet_UsersInRoles. This is a relatively simple 2 join query but I am not certain how to make it work using sequelize.
Here is that sequelize-auto code which was created:
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('aspnet_Roles', {
ApplicationId: {
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'aspnet_Applications',
key: 'ApplicationId'
}
},
RoleId: {
type: DataTypes.UUID,
allowNull: false,
primaryKey: true
},
RoleName: {
type: DataTypes.STRING(256),
allowNull: false
},
LoweredRoleName: {
type: DataTypes.STRING(256),
allowNull: false
},
Description: {
type: DataTypes.STRING(256),
allowNull: true
}
}, {
sequelize,
tableName: 'aspnet_Roles',
schema: 'dbo',
timestamps: false,
indexes: [
{
name: "aspnet_Roles_index1",
unique: true,
fields: [
{ name: "ApplicationId" },
{ name: "LoweredRoleName" },
]
},
{
name: "PK__aspnet_Roles__31EC6D26",
unique: true,
fields: [
{ name: "RoleId" },
]
},
]
});
};
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('aspnet_Users', {
ApplicationId: {
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'aspnet_Applications',
key: 'ApplicationId'
}
},
UserId: {
type: DataTypes.UUID,
allowNull: false,
primaryKey: true
},
UserName: {
type: DataTypes.STRING(256),
allowNull: false
},
LoweredUserName: {
type: DataTypes.STRING(256),
allowNull: false
},
MobileAlias: {
type: DataTypes.STRING(16),
allowNull: true
},
IsAnonymous: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
},
LastActivityDate: {
type: DataTypes.DATE,
allowNull: false
}
}, {
sequelize,
tableName: 'aspnet_Users',
schema: 'dbo',
timestamps: false,
indexes: [
{
name: "aspnet_Users_Index",
unique: true,
fields: [
{ name: "ApplicationId" },
{ name: "LoweredUserName" },
]
},
{
name: "aspnet_Users_Index2",
fields: [
{ name: "ApplicationId" },
{ name: "LastActivityDate" },
]
},
{
name: "PK__aspnet_Users__03317E3D",
unique: true,
fields: [
{ name: "UserId" },
]
},
]
});
};
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('aspnet_UsersInRoles', {
UserId: {
type: DataTypes.UUID,
allowNull: false,
primaryKey: true,
references: {
model: 'aspnet_Users',
key: 'UserId'
}
},
RoleId: {
type: DataTypes.UUID,
allowNull: false,
primaryKey: true,
references: {
model: 'aspnet_Roles',
key: 'RoleId'
}
}
}, {
sequelize,
tableName: 'aspnet_UsersInRoles',
schema: 'dbo',
timestamps: false,
indexes: [
{
name: "aspnet_UsersInRoles_index",
fields: [
{ name: "RoleId" },
]
},
{
name: "PK__aspnet_UsersInRo__35BCFE0A",
unique: true,
fields: [
{ name: "UserId" },
{ name: "RoleId" },
]
},
]
});
};
var DataTypes = require("sequelize").DataTypes;
var _aspnet_Applications = require("./aspnet_Applications");
var _aspnet_Membership = require("./aspnet_Membership");
var _aspnet_Paths = require("./aspnet_Paths");
var _aspnet_PersonalizationAllUsers = require("./aspnet_PersonalizationAllUsers");
var _aspnet_PersonalizationPerUser = require("./aspnet_PersonalizationPerUser");
var _aspnet_Profile = require("./aspnet_Profile");
var _aspnet_Roles = require("./aspnet_Roles");
var _aspnet_SchemaVersions = require("./aspnet_SchemaVersions");
var _aspnet_Users = require("./aspnet_Users");
var _aspnet_UsersInRoles = require("./aspnet_UsersInRoles");
var _aspnet_WebEvent_Events = require("./aspnet_WebEvent_Events");
var _aspnet_ZoneNumbers = require("./aspnet_ZoneNumbers");
var _aspnet_ZonePositions = require("./aspnet_ZonePositions");
function initModels(sequelize) {
var aspnet_Applications = _aspnet_Applications(sequelize, DataTypes);
var aspnet_Membership = _aspnet_Membership(sequelize, DataTypes);
var aspnet_Paths = _aspnet_Paths(sequelize, DataTypes);
var aspnet_PersonalizationAllUsers = _aspnet_PersonalizationAllUsers(sequelize, DataTypes);
var aspnet_PersonalizationPerUser = _aspnet_PersonalizationPerUser(sequelize, DataTypes);
var aspnet_Profile = _aspnet_Profile(sequelize, DataTypes);
var aspnet_Roles = _aspnet_Roles(sequelize, DataTypes);
var aspnet_SchemaVersions = _aspnet_SchemaVersions(sequelize, DataTypes);
var aspnet_Users = _aspnet_Users(sequelize, DataTypes);
var aspnet_UsersInRoles = _aspnet_UsersInRoles(sequelize, DataTypes);
var aspnet_WebEvent_Events = _aspnet_WebEvent_Events(sequelize, DataTypes);
var aspnet_ZoneNumbers = _aspnet_ZoneNumbers(sequelize, DataTypes);
var aspnet_ZonePositions = _aspnet_ZonePositions(sequelize, DataTypes);
aspnet_Roles.belongsToMany(aspnet_Users, { as: 'UserId_aspnet_Users', through: aspnet_UsersInRoles, foreignKey: "RoleId", otherKey: "UserId" });
aspnet_Users.belongsToMany(aspnet_Roles, { as: 'RoleId_aspnet_Roles', through: aspnet_UsersInRoles, foreignKey: "UserId", otherKey: "RoleId" });
aspnet_Membership.belongsTo(aspnet_Applications, { as: "Application", foreignKey: "ApplicationId"});
aspnet_Applications.hasMany(aspnet_Membership, { as: "aspnet_Memberships", foreignKey: "ApplicationId"});
aspnet_Paths.belongsTo(aspnet_Applications, { as: "Application", foreignKey: "ApplicationId"});
aspnet_Applications.hasMany(aspnet_Paths, { as: "aspnet_Paths", foreignKey: "ApplicationId"});
aspnet_Roles.belongsTo(aspnet_Applications, { as: "Application", foreignKey: "ApplicationId"});
aspnet_Applications.hasMany(aspnet_Roles, { as: "aspnet_Roles", foreignKey: "ApplicationId"});
aspnet_Users.belongsTo(aspnet_Applications, { as: "Application", foreignKey: "ApplicationId"});
aspnet_Applications.hasMany(aspnet_Users, { as: "aspnet_Users", foreignKey: "ApplicationId"});
aspnet_PersonalizationAllUsers.belongsTo(aspnet_Paths, { as: "Path", foreignKey: "PathId"});
aspnet_Paths.hasOne(aspnet_PersonalizationAllUsers, { as: "aspnet_PersonalizationAllUser", foreignKey: "PathId"});
aspnet_PersonalizationPerUser.belongsTo(aspnet_Paths, { as: "Path", foreignKey: "PathId"});
aspnet_Paths.hasMany(aspnet_PersonalizationPerUser, { as: "aspnet_PersonalizationPerUsers", foreignKey: "PathId"});
aspnet_UsersInRoles.belongsTo(aspnet_Roles, { as: "Role", foreignKey: "RoleId"});
aspnet_Roles.hasMany(aspnet_UsersInRoles, { as: "aspnet_UsersInRoles", foreignKey: "RoleId"});
aspnet_Membership.belongsTo(aspnet_Users, { as: "User", foreignKey: "UserId"});
aspnet_Users.hasOne(aspnet_Membership, { as: "aspnet_Membership", foreignKey: "UserId"});
aspnet_PersonalizationPerUser.belongsTo(aspnet_Users, { as: "User", foreignKey: "UserId"});
aspnet_Users.hasMany(aspnet_PersonalizationPerUser, { as: "aspnet_PersonalizationPerUsers", foreignKey: "UserId"});
aspnet_Profile.belongsTo(aspnet_Users, { as: "User", foreignKey: "UserId"});
aspnet_Users.hasOne(aspnet_Profile, { as: "aspnet_Profile", foreignKey: "UserId"});
aspnet_UsersInRoles.belongsTo(aspnet_Users, { as: "User", foreignKey: "UserId"});
aspnet_Users.hasMany(aspnet_UsersInRoles, { as: "aspnet_UsersInRoles", foreignKey: "UserId"});
return {
aspnet_Applications,
aspnet_Membership,
aspnet_Paths,
aspnet_PersonalizationAllUsers,
aspnet_PersonalizationPerUser,
aspnet_Profile,
aspnet_Roles,
aspnet_SchemaVersions,
aspnet_Users,
aspnet_UsersInRoles,
aspnet_WebEvent_Events,
aspnet_ZoneNumbers,
aspnet_ZonePositions,
};
}
module.exports = initModels;
module.exports.initModels = initModels;
module.exports.default = initModels;
You can add an "exclude" option in the attribute option of the query and exclude the given columns:
test.aspnet_Users.findAll({
logging: console.log,
where: { LoweredUserName: `mcad2\\${user}` },
attributes: { exclude: ['userID'], include: ['LoweredUserName'] },
include: {
model: test.aspnet_Roles,
as: 'RoleId_aspnet_Roles',
attributes: { exclude: ['roleID'], include: ['LoweredRoleName'] },
}
}).then(user => {
console.log('\n\n' + JSON.stringify(user))
})
If I understood your structure correctly this should exclude userID and roleID in the fetched data.

Node Sequelize inserting wrong field position on many to many table

I have a many to many relationship between the tables DeliveryOrder and GasBottle with the extra field Amount, but when i try to insert some values in this table, sequelize change´s the field order.
My models:
const {Model,DataTypes} = require ('sequelize')
class GasBottle extends Model{
static init(sequelize){
super.init({
type: DataTypes.INTEGER,
costPrice: DataTypes.DOUBLE,
sellPrice: DataTypes.DOUBLE
},{sequelize})
}
static associate({ DeliveryOrder,DeliveryOrderGasBottle}) {
GasBottle.belongsToMany(DeliveryOrder, {
through: DeliveryOrderGasBottle,
as: "deliveryOrders",
foreignKey: "deliveryOrderId",
});
}
}
module.exports = GasBottle
const { Model, DataTypes } = require("sequelize");
class DeliveryOrder extends Model {
static init(sequelize) {
super.init(
{
status: DataTypes.INTEGER,
latitude: DataTypes.INTEGER,
longitude: DataTypes.INTEGER,
delivererId: {
type: DataTypes.INTEGER,
references: {
model: "Deliverer",
key: "id",
},
},
},
{ sequelize }
);
}
static associate({ Deliverer, GasBottle, DeliveryOrderGasBottle }) {
DeliveryOrder.belongsTo(Deliverer, { foreignKey: "delivererId" });
DeliveryOrder.belongsToMany(GasBottle, {
through: DeliveryOrderGasBottle,
as: "bottles",
foreignKey: "gasBottleId",
});
}
}
module.exports = DeliveryOrder;
const { Model, DataTypes } = require("sequelize");
class DeliveryOrderGasBottle extends Model {
static init(sequelize) {
super.init(
{
gasBottleId: {
type: DataTypes.INTEGER,
references: {
model: "GasBottle",
key: "id",
},
},
deliveryOrderId: {
type: DataTypes.INTEGER,
references: {
model: "DeliveryOrder",
key: "id",
},
},
amount: DataTypes.INTEGER,
},
{ sequelize }
);
}
}
module.exports = DeliveryOrderGasBottle;
My migration file:
"use strict";
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable("DeliveryOrderGasBottle", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
gasBottleId: {
type: Sequelize.INTEGER,
references: {
model: "GasBottle",
key: "id",
},
allowNull: false,
onDelete: "CASCADE",
},
deliveryOrderId: {
type: Sequelize.INTEGER,
references: {
model: "DeliveryOrder",
key: "id",
},
allowNull: false,
onDelete: "CASCADE",
},
amount:{
type: Sequelize.DOUBLE,
allowNull: false,
},
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable("DeliveryOrderGasBottle");
},
};
My association:
const deliveryOrder = await DeliveryOrder.create(obj);
bottlesToAdd.map(async (bottle) => {
const db_bottle = await GasBottle.findByPk(bottle.id);
await deliveryOrder.addBottle(db_bottle, {
through: { amount: parseInt(bottle.amount) },
});
On insert, sequelize is changing the order of the ids, resulting in a constraint error because i dont have the id´s on the respective tables
INSERT INTO "DeliveryOrderGasBottle" ("gasBottleId","deliveryOrderId","amount","createdAt","updatedAt") VALUES (18,1,42,'2020-06-27 19:17:26.204 +00:00','2020-06-27 19:17:26.204 +00:00')

Sequelize: Bind multiple models for join query and create custom columns

I'd like to apply a join and groupBy in Sequelize v5 that will fetch the records from five models tables and return the records as below format.
{
"data": [
{
"products": {
"id": "01",
"name": "lorium",
"description": "ipsum",
"product_images": [
{
"url": "", // From images tbl
"image_type": "Front" // From imge_types tbl
},
{
"url": "",
"image_type": "Back"
}
]
},
"vendor": {
"first_name": "john",
"last_name": "doe"
}
}
]
}
I have created separate all five models and assign association to them.
Product Model::
const Product = SQLize.define('product', {
id: { type: DataTypes.INTEGER.UNSIGNED, autoIncrement: true, primaryKey: true, }
product_title: { type: new DataTypes.STRING(255) },
vendor_id: { type: DataTypes.INTEGER.UNSIGNED }
});
Product.hasMany(ProductImages, {foreignKey: 'product_id', targetKey: 'id', as :'product_img_refs'})
export { Product };
Vendor Model::
const Vendor = SQLize.define('vendor', {
id: { type: DataTypes.INTEGER.UNSIGNED, autoIncrement: true, primaryKey: true, },
first_name: { type: DataTypes.STRING(100) },
last_name: { type: DataTypes.STRING(100) }
});
Product.belongsTo(Vendor, {foreignKey: 'id'})
Vendor.hasOne(Product, {foreignKey: 'id'})
export { Vendor }
Product Images Model::
const ProductImages = SQLize.define('product_images', {
id: { type: DataTypes.INTEGER.UNSIGNED, autoIncrement: true, primaryKey: true, },
product_id: { type: DataTypes.INTEGER },
product_image_id: { type: DataTypes.INTEGER }
img_type_id: { type: DataTypes.INTEGER }
});
export {ProductImages}
Images Model::
const ImagesModel = SQLize.define('images', {
id: { type: DataTypes.INTEGER.UNSIGNED, autoIncrement: true, primaryKey: true, },
img_url: { type: DataTypes.STRING }
});
export { ImagesModel }
Image Types Model::
const ImageTypes = SQLize.define('image_types', {
id: { type: DataTypes.INTEGER.UNSIGNED, autoIncrement: true, primaryKey: true, },
image_type: { type: DataTypes.STRING }
});
export { ImageTypes }
Below is the repository file on which i have performed the SQLize operation: Updated::
public async getProductData() {
var prodData = Product.findAll({
include: [
{ model: Vendor, as: 'vendor' },
{ model: ProductImages, as: 'product_img_refs' }
]
});
return prodData;
}
I am not getting the correct way to bind the all models that will return me a result as described in the above json format.
To get the nested output as shown in the question, you would need to create associations between the following:
ProductImages and ImagesModel
ProductImages and ImageTypes
Once done, you can nest the models in the findAll options as shown below:
// Create associations (depends on your data, may be different)
ProductImages.hasOne(ImagesModel);
ProductImages.hasOne(ImageTypes);
// Return product data with nested models
let prodData = Product.findAll({
include: [
{ model: Vendor, as: 'vendor' },
{
model: ProductImages, as: 'product_img_refs',
include: [
{ model: ImagesModel }, // Join ImagesModel onto ProductImages (add aliases as needed)
{ model: ImageTypes } // Join ImageTypes onto ProductImages (add aliases as needed)
]
}
]
});
I found the issue. you were trying to include ProductImages model into Vendor. As per your association, ProductImages associate with Product not with Vendor.
So please try this
let prodData = Product.findAll({
include: [
{ model: Vendor, as: 'vendor' },
{ model: ProductImages }
]
});

Resources