Sequelize Subqueries - node.js

in this case i want to find the total prepare time for each order according the orderId, but when i write like this it only shows 1 result which is the first one,
let prepareOrder = await OrderItem.findAll({
where: {
options: null,
},
attributes: ["orderId"],
include: [
{
model: Item,
attributes: [
[
sequelize.fn("sum", sequelize.col("prepareTime")),
"totalPrepareTime",
],
],
},
],
});

You need to rum SUM() on the outer query. When you run it on the inner query it is returning a single row and then doing a JOIN which is why you only get one row.
const prepareOrder = await OrderItem.findAll({
attributes: [
"orderId",
// get the summary at the OrderItem for each related Item
[
sequelize.fn("sum", sequelize.col("item.prepareTime")),
"totalPrepareTime",
],
],
// include Item but no attributes for performance
include: {
model: Item,
attributes: [],
},
where: {
options: null,
},
});

Related

Sequelize: order-by doesn't seem to work on aggregated output while using multiple joins

I've been trying to order the results by total no. of all reviews given for a particular seller's store.
All associations are defined but when I tried order by on avg(ratings) or count(id) [here id is id of alias named 'seller_details'], it gives me an error. I have tried many ways like using Sequelize.col() and giving all models names; using Sequelize.literal() but none works.
const data = await UserFavoriteStores.findAndCountAll({
where: {
customer_id: userId
},
include: [
{
model: SellerStoreDetail,
required: false,
include: [
{
model: StoreReviews,
required: false,
attributes: [],
as: 'seller_details'
}
],
attributes: {
include: [
[
Sequelize.fn(
'count',
Sequelize.col('favStoreData.seller_details.id')
),
'totalReviewCount'
],
[
Sequelize.fn(
'AVG',
Sequelize.col('favStoreData.seller_details.rating')
),
'avgRating'
]
]
},
as: 'favStoreData'
}
],
group: ['user_favorite_stores.id', 'favStoreData.id'],
limit: limit,
offset: skip,
subQuery: false
});

fetching data using sequelize

i have player table has name and profileId
profile table has numberOfKills ,rankId and power
rank table has rankName
i want to get all players data from above orderd by rank top 100
using this code
let players: any = await Player.findAll({
attributes: [
'name',
'profile.numberOfKills',
'profilepower',
'profile.rankId',
],
include: [
{
model: Profile,
include: [
{
model: Level,
attributes: ['name'],
as: 'rank',
},
],
},
],
order: ['profile.numberOfKills', 'DESC'],
limit: 100,
});
"message": "Cannot read properties of undefined (reading 'type')"
what to do
using sequelize and not literal query
The order should be an array that contains either another array per field you want to sort on or functions like sequelize.random(), sequelize.col('name'), etc.
Change:
order: ['profile.numberOfKills', 'DESC'],
to:
order: [
['profile.numberOfKills', 'DESC'],
],
I'm using literal and it works!
order: [
[sequelize.literal('`profile.numberOfKills`'), 'DESC']
]

Adding order clause in queries with nested association in Sequelize

I trying to fetch the assessment details for a class in which assessment_test model has association with student_assessment_test model(hasMany). I want the fetched result ordered according to the marks obtained by student. I am trying the below method but it doesn't seem to be working. Please let me know the correct method for such queries.
const assessmentDetails = await Entity.assessmentTest.findOne({
where: { id: assessmentId, status: 1 },
attributes: [
'id',
'sectionId',
'assessmentDate',
'assessmentTitle',
'totalPoints',
],
include: [
{
association: 'assessmentTestDetails',
where: { status: 1 },
attributes: ['marksObtained', 'percentage', 'testStatus'],
required: true,
order: [['marksObtained', 'ASC']],
include: [
{
association: 'student',
where: { status: 1 },
attributes: ['studentName'],
required: true,
},
],
},
],

How do I group by a column in a nested association in sequelize.js?

I'm trying to implement the following SQL query using sequelize.js:
select
practtype.description,
SUM("chargevalue") as "categoryvalue"
from
"public"."profees" as "profees"
inner join "public"."practitioners" AS "practitioner" on
"profees"."practitionerid" = "practitioner"."practitionerid"
inner join public.practtypes as "practtype" on
"practitioner"."practtypeid" = "practtype"."practtypeid"
group by
practtype.description
order by
practtype.description;
I have the following associations set up in my init-models.js component:
profees.belongsTo(practitioners, { as: "practitioner", foreignKey: "practitionerid"});
practitioners.hasMany(profees, { as: "profees", foreignKey: "practitionerid"});
practitioners.belongsTo(practtypes, { as: "practtype", foreignKey: "practtypeid"});
practtypes.hasMany(practitioners, { as: "practitioners", foreignKey: "practtypeid"});
I'm struggling to find decent documentation or examples of how to specify the group clause of my sequelize query. Here's what I currently have:
const feesSummary = await profees.findAll({
attributes: [
[sequelize.fn("SUM", sequelize.col("chargevalue")), "categoryvalue"],
// ["chargevalue", "categoryvalue"],
],
include: [
{
model: practitioners,
as: "practitioner",
required: true,
attributes: ["surname"],
include: [
{
model: practtypes,
as: "practtype",
required: true,
attributes: ["description"],
},
],
},
],
group: [
[
{ model: practitioners, as: "practitioner" },
{ model: practtypes, as: "practtype" },
"description",
],
],
order: [
[
{ model: practitioners, as: "practitioner" },
{ model: practtypes, as: "practtype" },
"description",
"ASC",
],
],
// where: sequelize.where(sequelize.fn("date_part", ["year", sequelize.col("chargedate")]), year)
});
(I've commented out the where clause for the time being, as it's also giving me separate issues).
When I try to execute the sequelize query above, I get the following error:
Error: Unknown structure passed to order / group: { model: practitioners, as: 'practitioner' }
at PostgresQueryGenerator.quote (/home/developer/medexpenses/medexps-service/node_modules/sequelize/lib/dialects/abstract/query-generator.js:888:11)
at PostgresQueryGenerator.aliasGrouping (/home/developer/medexpenses/medexps-service/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1418:17)
at /home/developer/medexpenses/medexps-service/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1343:82
at Array.map (<anonymous>)
at PostgresQueryGenerator.selectQuery (/home/developer/medexpenses/medexps-service/node_modules/sequelize/lib/dialects/abstract/query-generator.js:1343:68)
at PostgresQueryInterface.select (/home/developer/medexpenses/medexps-service/node_modules/sequelize/lib/dialects/abstract/query-interface.js:954:27)
at Function.findAll (/home/developer/medexpenses/medexps-service/node_modules/sequelize/lib/model.js:1753:47)
I'm using version 6.6.2 of sequelize.
Can anyone post an example of the correct way to formulate the group clause in the query above? The Sequelize documentation suggests that
The syntax for grouping and ordering are equal, except that grouping does not accept a direction as last argument of the array (there is no ASC, DESC, NULLS FIRST, etc).
which is why I formulated the group clause as I did, but I'm getting the error above nonetheless.

Group By with Sequelize

I have the following class structure:
I'm trying to group and count by Sequelize how many titles each selection had from the Cup_Selections table equal to the query typed below:
My Node query with Sequelize is as follows:
async index(req, res) {
const champions = await Champion.findAll({
attributes: ['id', 'cupselection_id'],
include: [
{
group: ['selection_id', 'champion.id'],
raw: true,
model: CupSelection,
as: 'cupselection',
attributes: [
'id',
'cup_id',
[fn('count', col('selection_id')), 'vezes'],
],
include: [
{
model: Selection,
as: 'selection',
attributes: ['id', 'country'],
},
],
},
],
});
return res.json(champions);
}
But the following error is displayed to me:
(node:28230) UnhandledPromiseRejectionWarning: SequelizeDatabaseError: column "Champion.id" must appear in the GROUP BY clause or be used in an aggregate function
How can I solve ?
I solved it as follows:
async index(req, res) {
const { page = 1 } = req.query;
const champions = await Champion.findAll({
limit: 5,
offset: (page - 1) * 5,
order: [[fn('count', col('cupselection.selection.id')), 'DESC']],
attributes: [[fn('count', col('cupselection.selection.id')), 'vezes']],
group: ['cupselection.selection.id', 'cupselection.selection.logo.id'],
raw: true,
include: [
{
model: CupSelection,
as: 'cupselection',
attributes: [],
include: [
{
model: Selection,
as: 'selection',
attributes: ['id', 'country'],
include: [
{
model: File,
as: 'logo',
attributes: ['id', 'path', 'url'],
},
],
},
],
},
],
});
return res.json(champions);
}

Resources