fetching data using sequelize - node.js

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']
]

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 with aggrigation

i have (gang) tabel contain many profiles, id and a name
each profile has numberOfkills ,power and other data
i want to get top 20 gangs name with sum of numberOfKills group by gangName ordered by numberOfKillsSum
using this code
let gangs = await Gang.findAll({
attributes: [
'name',
[
Sequelize.fn('SUM', Sequelize.col('profile.numberOfKills')),
'numberOfKillSum',
],
],
group: ['name'],
order: [
['numberOfKillSum', 'DESC'],
],
limit: 100,
include: [
{
model: Profile,
}
]
})
testing it getting me this error
"missing FROM-clause entry for table "profile""
how should i fix it ?

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.

Sequelize Subqueries

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,
},
});

Ordering results of eager-loaded nested models in Node Sequelize

I have a complex set of associated models. The models are associated using join tables, each with an attribute called 'order'. I need to be able to query the parent model 'Page' and include the associated models, and sort those associations by the field 'order'.
The following is having no effect on the results' sort order:
db.Page.findAll({
include: [{
model: db.Gallery,
order: ['order', 'DESC'],
include: [{
model: db.Artwork,
order: ['order', 'DESC']
}]
}],
})
I believe you can do:
db.Page.findAll({
include: [{
model: db.Gallery
include: [{
model: db.Artwork
}]
}],
order: [
// sort by the 'order' column in Gallery model, in descending order.
[ db.Gallery, 'order', 'DESC' ],
// then sort by the 'order' column in the nested Artwork model in a descending order.
// you need to specify the nested model's parent first.
// in this case, the parent model is Gallery, and the nested model is Artwork
[ db.Gallery, db.ArtWork, 'order', 'DESC' ]
]
})
There are also a bunch of different ways, or things you can do when ordering. Read more here: https://sequelize.org/master/manual/model-querying-basics.html#ordering-and-grouping
If you also use 'as' and let's say you want to order by 'createdDate' , the query looks like this:
DbCategoryModel.findAll({
include: [
{
model: DBSubcategory,
as: 'subcategory',
include: [
{
model: DBProduct,
as: 'product',
}
],
}
],
order: [
[
{model: DBSubcategory, as: 'subcategory'},
{model: DBProduct, as: 'product'},
'createdDate',
'DESC'
]
]
})
order: [
[ db.Sequelize.col('order'), 'DESC'], /*If you want to order by page module as well you can add this line*/
[ db.Gallery, db.ArtWork, 'order', 'DESC' ]
]
This works for me:
let getdata = await categories_recipes.findAll({
order:[
[{model: recipes, as: 'recipesdetails'},'id', 'DESC'] // change your column name like (id and created_at)
],
include:[{
model:recipes, as : "recipesdetails",
include:[{
model:recipe_images, as: "recipesimages",
}],
where:{
user_id:data.id
},
required: true,
}]
})
Just for completeness, another thing that also works is using sequelize.col as in:
db.Page.findAll({
include: [{
model: db.Gallery
include: [{
model: db.Artwork
}]
}],
order: [
[ sequelize.col('Gallery.order', 'DESC' ],
[ sequelize.col('Gallery.Artwork.order', 'DESC' ]
]
})
In this particular case it is slightly worse than the Arrays from https://stackoverflow.com/a/30017078/895245 (which more explicitly use existing Js classes rather than magic strings) but it seems that in most cases besides order:, .col is accepted but arrays aren't so it is good to have it in mind too.
There are some additional difficulties to overcome when you also need to limit: in nested includes:
how can i use limit in include model using sequelize
https://github.com/sequelize/sequelize/issues/8802
When limiting on toplevel only, it seems that subQuery: false is required e.g. as in:
u0WithComments = await User.findOne({
where: { id: u0.id },
order: [[
'Comments', 'body', 'DESC'
]],
limit: 1,
subQuery: false,
include: [{
model: Comment,
}],
})

Resources