fetching data using sequelize with aggrigation - node.js

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 ?

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

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

NodeJS Sequelize make main table descending example

I got stuck how to make descending main table in NodeJS. I've developed like that
models.Users.findAll({
where: {id: usersArray},
include: [
{model: models.Users_Answers}
],
order: [
[models.Users_Answers, 'id', 'ASC']
]
}).then(function(answers) {
/* Do something */
});
But error encountered when I changed as below, error encountered.
models.Users.findAll({
where: {id: usersArray},
include: [
{model: models.Users_Answers}
],
order: [
[models.Users, 'id', 'DESC']
[models.Users_Answers, 'id', 'ASC']
]
}).then(function(answers) {
/* Do something */
});
Unhandled rejection Error: 'Users' in order / group clause is not
valid association
You need to do it like this,
models.Users.findAll({
where: {id: usersArray},
include: [
{model: models.Users_Answers}
],
order: [
[db.Sequelize.col('id'), 'DESC'],
[models.Users_Answers, 'id', 'ASC']
]
}).then(function(answers) {
/* Do something */
});

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