Order by in nested eager loading in sequelize not working - node.js

i have four model Tehsil, Ilr, Patwar, and Villages.
and their association is
Tehsil -> 1:m -> Ilr -> 1:m -> Patwar -> 1:m -> Villages
i want to to apply order by on all four of my models.
Query:
var tehsilQuery = {
include: [{
model: Ilr,
as: 'GirdawariKanoongo',
include: [{
model: Patwar,
as: 'GirdawariPatwar',
include: [{
model: Villages,
as: 'GirdawariVillages',
}]
}]
}],
order: [
['tehsil_name', 'ASC'],
[ {model: Ilr, as: 'GirdawariKanoongo'}, 'kanoongo_name', 'ASC'],
[ {model: Patwar, as: 'GirdawariPatwar'}, 'patwar_area', 'ASC'],
[ {model: Villages, as: 'GirdawariVillages'}, 'village_name', 'ASC'],
]
};
return Tehsils.findAll(tehsilQuery);
[Error: 'girdawari_patwar' in order / group clause is not valid association]
order by is working if i remove Patwar and Villages(lat two model) from order.

Another working example with nested ordering:
order: [
[ { model: chapterModel, as: 'Chapters' }, 'createdAt', 'ASC'],
[ { model: chapterModel, as: 'Chapters' },
{ model: partModel, as: 'Parts' }, 'createdAt', 'ASC']
],
where part and chapter have M:1 relation.

Our scenario was with two nested include statements where the inner most nesting was not ordering correctly. By applying the ordering at the highest level of the findAll we were able to successfully return the ordered object.
model relationship as follows for our surveySet.findAll:
suveySet hasMany surveys
surveys belongsToMany questions
order: [
[ { model: survey, as: 'survey' }, 'subjectId', 'ASC'],
[ { model: survey, as: 'survey' },
{ model: question, as: 'question' }, 'id', 'ASC']
]

i solved it.
here's how order looks:
order: [
'tehsil_name',
'GirdawariKanoongo.kanoongo_name',
'GirdawariKanoongo.GirdawariPatwar.patwar_area',
'GirdawariKanoongo.GirdawariPatwar.GirdawariVillages.village_name'
]
all i have to do is: using the as in association of table and chaining them followed by column_name on which order supposed to apply.

For anyone wondering how it could be achieved using object style definition, this is how it would be solved.
You could find more information about ordering in Sequelize documentation.
order: [
['tehsil_name', 'ASC'],
[ {model: Ilr, as: 'GirdawariKanoongo'}, 'kanoongo_name', 'ASC'],
[ {model: Ilr, as: 'GirdawariKanoongo'}, {model: Patwar, as: 'GirdawariPatwar'}, 'patwar_area', 'ASC'],
[ {model: Ilr, as: 'GirdawariKanoongo'}, {model: Patwar, as: 'GirdawariPatwar'}, {model: Villages, as: 'GirdawariVillages'}, 'village_name', 'ASC'],
]

Related

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

issue in specifying attribute name while eagerLoading in Sequelize

I have a model and doing eager Loading in using findAll().
The issue is when I use sequelize.col("ColName"), it only works in first level of include.
But it gives an error ERROR Invalid column name 'exerciseLocation.name when I use it in the depper level JOIN (I've already added alias in the associations)
sequelize version : 6.14.1
Here is my code
Scheduler.findAll({
where: { userId: _userId },
attributes: [
"id",
"title",
[db.sequelize.col("Location.name"), "location"], // This works fine
],
include: [
{
model: Locations,
attributes: [],
},
{
model: ExerciseList,
attributes: [
"id",
"title",
[db.sequelize.col("exerciseLocation.name"), "location"], /* ERROR Invalid column name 'exerciseLocation.name'*/
],
include: [
{
model: Locations,
attributes: [],
},
],
},
],
})
My associations
db.Scheduler.belongsTo(db.Locations, {foreignKey: "location",});
db.Scheduler.hasMany(db.ExerciseList, {foreignKey: "SchedulerId",});
db.ExerciseList.belongsTo(db.Scheduler, {foreignKey: "SchedulerId",});
db.ExerciseList.belongsTo(db.Exercises, {foreignKey: "exerciseId",});
db.ExerciseList.belongsTo(db.Locations, {foreignKey: "locationId", as: 'exerciseLocation'});

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 - SQL Server - order by for association tables

I have 3 tables such as user, userProfile and userProfileImages. User is mapping with userPrfoile as has many and userProfile is mapping with userProfileImages as has many.
I need to write the order by query in userProfileImages, I tried as below, but no luck.
User.findById(uID, {
include: [
model: sequelize.models.userProfile
as: userProfile,
include: [
{
model: sequelize.models.userProfileImages,
as: 'profileImages',
}
],
order: [[sequelize.models.userProfileImages.id, "desc"]]
// order: [["id", "desc"]] --> Tried this way also no luck
] }
I am getting the result, but userProfilePicture table's result is not as desc.
Kindly give the solutions
From Sequelize offical docs:
// Will order by an associated model's created_at using an association object. (preferred method)
[Subtask.associations.Task, 'createdAt', 'DESC'],
// Will order by a nested associated model's created_at using association objects. (preferred method)
[Subtask.associations.Task, Task.associations.Project, 'createdAt', 'DESC'],
By referring above syntax, Update your order option like below
User.findById(uID, {
include: [{
model: sequelize.models.userProfile
as: userProfile,
include: [{
model: sequelize.models.userProfileImages,
as: 'profileImages',
}],
order: [['profileImages','id', 'desc']]
}]
});
Official Documentations: http://docs.sequelizejs.com/manual/tutorial/querying.html#ordering
Refer this thread for more solutions: https://github.com/sequelize/sequelize/issues/4553
Update your order in association like below
User.findById(uID, {
include: [
model: sequelize.models.userProfile,
as: userProfile,
include: [{
model: sequelize.models.userProfileImages,
as: 'profileImages',
separate:true, <-- Magic here
order: [['id', 'desc']]
}],
]});

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