sequelize get column value of referenced table - node.js

I have three tables meetings, rooms and projects
meetings.belongsTo(models.rooms, { foreignKey: "room_id" , targetKey: "id"});
rooms.hasMany(models.meetings, { foreignKey : "id", targetKey : "room_id"});
rooms.belongsTo(models.projects, { foreignKey: "project_id", targetKey: "id"});
projects.hasMany(models.rooms, {foreignKey:"id", targetKey:"project_id"});
id, room_id and project_id are primary key of their respective table.
I want to find value of some column of projects for a particular meeting id. How to write a single query using sequelize nodejs to do this?
below query need to execute using sequelize which is giving correct result
select project_meta from projects p
inner join rooms r on p.id = r.project_id
inner join meetings m on r.id = m.room_id
where m.id = "QBZJ0TK7V6NFSPPWGFNCN";
wrote following
projects.findAll({
include: [{
model: rooms,
include: [{
model: meetings,
where: {
id: "QBZJ0TK7V6NFSPPWGFNCN"
}
}]
}],
attributes: ['project_meta']
}
but it is executing different query and giving unexpected result
is there any problem with association?

You must use SQL joins (sequelize's include)
function myQuery(meetingId) {
let options = {};
options.attributes = ['column1', 'column2', ...]; // The specific arrtibutes you need.
options.include = [
{
model: RoomModel,
include: [
{
model: MeetingModel,
where: {
id: meetingId // The specific meeting id
}
}
]
}
];
ProjectModel.findAll(options);
}

Related

Sequelize join two tables on id

I have a table of book users and a table of movie users. I'm trying to return a list of the top 100 movie viewers, along with their book profile information. I want to join on ids, but I can't seem to find the right syntax.
This is what I've tried:
const mostActiveMovieWatchers = await MovieWatchers.findAll({
order: [
['moviesWatched', 'DESC'],
],
limit: '100',
include: [{
model: BookReaders,
where: {
userId: '$MovieWatchers.id$'
},
required: true
}]
});
I've also seen examples where the where clause looks something like this where: ['userId = id']
Before join tables you need create association:
BookReaders.hasMany(MovieWatchers, { foreignKey: 'bookId' });
MovieWatchers.belongsTo(BookReaders, { foreignKey: 'bookId' });
Then, you can use the include option in a find or findAll method call on the MovieWatchers model to specify that you want to include the associated BookReaders data:
MovieWatchers.findAll({
include: [
{
model: BookReaders,
},
],
}).then((movies) => {
// array of movies including books
});

How Can I write INNER Join query using Sequelize on Node.js

I have two tables. One is tblEmailAuditLog having columns Id, OrderId, Body, CommunicationType, CreatedOn, Reciever, WorkflowStatusId, IsSuccess another one is tblLookUp having column names as LU_LookUpValue and LU_LOOKUPID. I want to join the two tables based on the columns (CommunicationType and LU_LOOKUPID)
My inner join query looks as below:
select Id, OrderId, Body, CommunicationType, CreatedOn, Reciever, WorkflowStatusId, IsSuccess, LU_LookUpValue from tblEmailAuditLog INNER JOIN tblLookUp on tblEmailAuditLog.CommunicationType = tblLookUp.LU_LOOKUPID;
I am trying to write the above query using sequelize ORM.
I have tried the below things.
1.
let auditLogs = await MediMarket.TblEmailAuditLog.findAll({
include: [
{
model: MediMarket.TblLookUp,
required: true,
where: { orderId: req.body.orderId },
},
],
});
2.
let auditLogs = MediMarket.TblEmailAuditLog.hasMany(
MediMarket.TblLookUp,
{ foreignKey: "CommunicationType" }
);
MediMarket.TblLookUp.belongsTo(MediMarket.TblEmailAuditLog, {
foreignKey: "LU_LOOKUPID",
});
MediMarket.TblEmailAuditLog.findAll({
where: { orderId: req.body.orderId },
include: [MediMarket.TblLookUp],
});
But it is not giving the expected result.

Inner join query in Sequelize referencing multiple tables

HOW DO I WRITE BELOW QUERY IN SEQUELIZE?
select vdc_id,vdc.name as vdc,
districts.name as district,
states.name as state,
countries.name as country
from vdc
INNER JOIN districts on (vdc.district_id=districts.district_id and vdc.name like 'L%')
INNER JOIN states on (districts.state_id=states.state_id)
INNER JOIN countries on (states.country_id=countries.country_id)
order by district asc;
Associations :
vdc table contains fk_district_id
db.vdc.belongsTo(db.districts,{
foreignKey:"district_id"
})
db.districts.hasMany(db.vdc,{
foreignKey:"district_id"
})
districts table contains fk_state_id
db.districts.belongsTo(db.states,{
foreignKey:"state_id"
})
db.states.hasMany(db.districts,{
foreignKey:"state_id"
})
states table contains fk_country_id
db.states.belongsTo(db.countries,{
foreignKey:"country_id"
})
db.countries.hasMany(db.states,{
foreignKey:"country_id"
})
THANKS YOU!
It seems you would need something like the code below. You would need to adjust it to work with your models since they were not provided, but this should give you an idea of what is required to get the query you want.
vdc.findAll({
attributes: ['vcd_id', 'name'],
include: [
{
model: 'districts', // Or districts model
attributes: [['name', 'district']], // name as district
required: true, // Use inner join instead of left join
on: { // Join on district id and name like 'L%'
'district_id': { [Op.eq]: sequelize.col('districts.district_id') },
'name': { [Op.like]: 'L%' }
}
},
// Custom join shouldn't be necessary for the following due to foreign key config
{
model: 'states',
attributes: [['name', 'state']],
required: true
},
{
model: 'countries',
attributes: [['name', 'country']],
required: true
}
],
order: [['district', 'ASC']]
});

Multiple tables join issue in sequelize in node js

I have 6 tables
Employees,Salary,Deduction,DeductionTypes,Allowance,AllowancesTypes
Here is the table relations with a diagram
I can't understand how to create a join query
Employee.belongsTo(Salary, { foreignKey: 'employee_id' });
Salary.belongsToMany(Deduction, {foreignKey: 'salary_id' });
Deduction.belongsToMany(DeductionType, {foreignKey: 'deduction_type_id' });
Salary.belongsToMany(Allowance, {foreignKey: 'salary_id' });
Allowance.belongsToMany(AllowanceType, {foreignKey: 'allowance_type_id' });
Here is my find query
const payRunData = Employee.findAll({
include: [{
model: Salary, attributes: ['salary_id', 'basic_salary'],
include: [
{
model: Deduction, attributes: ['amount'],
include: [{
model: DeductionType, attributes: ['epf_enable', 'type', 'pre_tax', 'pay_run_editable'],
}]
},
{
model: Allowance, attributes: ['amount'],
include: [{
model: AllowanceType, attributes: ['epf_enable', 'type', 'payee_enable', 'pay_run_editable'],
}]
}
]
}
],
attributes: ['employee_id', 'given_names'],
});
Here is the sql join query what I'm expecting
select s.salary_id , e.employee_id, e.given_names, d.amount as 'deduction_amount',
dty.`type` as 'deduction_type', dty.epf_enable as 'deductType_epf_enable', dty.pre_tax, dty.pay_run_editable as 'deductType_pay_run_editable',
a.amount as 'allowance_amount', aty.`type`as 'allowanceType_type', aty.epf_enable as 'allowanceType_epf_enable',
aty.payee_enable as 'allowanceType_payee', aty.pay_run_editable as 'allowanceType_pay_run_editable'
from employees as e inner join salary as s on e.employee_id = s.salary_id
inner join deductions as d on s.salary_id = d.salary_id
inner join deduction_types as dty on d.deduction_type_id = dty.deduction_type_id
inner join allowances as a on s.salary_id = a.salary_id
inner join allowance_types as aty on a.allowance_type_id = aty.allowance_type_id
When I execute this,it's returning this error
salary.belongsToMany(deduction) requires through option, pass either a
string or a model"
please help me to solve this

How to count a group by query in NodeJS Sequelize

In Rails I can perform a simple ORM query for the number of Likes a model has:
#records = Model
.select( 'model.*' )
.select( 'count(likes.*) as likes_count' )
.joins( 'LEFT JOIN likes ON model.id = likes.model_id' )
.group( 'model.id' )
This generates the query:
SELECT models.*, count(likes.*) as likes_count
FROM "models" JOIN likes ON models.id = likes.model_id
GROUP BY models.id
In Node Sequelize, any attempt at doing something similar fails:
return Model.findAll({
group: [ '"Model".id' ],
attributes: ['id', [Sequelize.fn('count', Sequelize.col('"Likes".id')), 'likes_count']],
include: [{ attributes: [], model: Like }],
});
This generates the query:
SELECT
Model.id,
count(Likes.id) AS likes_count,
Likes.id AS Likes.id # Bad!
FROM Models AS Model
LEFT OUTER JOIN Likes
AS Likes
ON Model.id = Likes.model_id
GROUP BY Model.id;
Which generates the error:
column "Likes.id" must appear in the GROUP BY clause or be used in an aggregate function
It's erroneously selecting likes.id, and I have no idea why, nor how to get rid of it.
This sequelize github issue looks totally like your case:
User.findAll({
attributes: ['User.*', 'Post.*', [sequelize.fn('COUNT', 'Post.id'), 'PostCount']],
include: [Post]
});
To resolve this problem we Need to upgrade to latest version of sequelize and include raw = true,
Here is How I had done after lot of iteration and off-course googling.
getUserProjectCount: function (req, res) {
Project.findAll(
{
attributes: ['User.username', [sequelize.fn('COUNT', sequelize.col('Project.id')), 'ProjectCount']],
include: [
{
model: User,
attributes: [],
include: []
}
],
group: ['User.username'],
raw:true
}
).then(function (projects) {
res.send(projects);
});
}
where my reference models are
//user
var User = sequelize.define("User", {
username: Sequelize.STRING,
password: Sequelize.STRING
});
//project
var Project = sequelize.define("Project", {
name: Sequelize.STRING,
UserId:{
type:Sequelize.INTEGER,
references: {
model: User,
key: "id"
}
}
});
Project.belongsTo(User);
User.hasMany(Project);
after migration ORM create 'Users' & 'Projects' table into my postgres server.
Here is SQL Query by ORM
SELECT
"User"."username", COUNT("Project"."id") AS "ProjectCount"
FROM
"Projects" AS "Project"
LEFT OUTER JOIN "Users" AS "User" ON "Project"."UserId" = "User"."id"
GROUP BY
"User"."username";
What worked for me counting column A and grouping by column B
const noListingsPerRetailer = Listing.findAll({
attributes: [
'columnA',
[sequelize.fn('COUNT', sequelize.col('columnB')), 'labelForCountColumn'],
],
group:["columnA"]
});

Resources