Sequelize - SQL Server - order by for association tables - node.js

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

Related

How do you join 3 tables in Sequelize that aren't all linked

I have 4 tables Properties, Units, Leases, LeaseRates.
Units
Leases
LeaseRates
propertyId
unitId
leaseId
they are all connected with the id of the last one.
I have these relationships setup like this
Properties.hasMany(Units);
Units.belongsTo(Properties);
Units.hasMany(Leases);
Leases.belongsTo(Units);
Leases.hasMany(LeaseRates);
LeaseRates.belongsTo(Leases);
Is there an easy way in Sequelize for me to query LeaseRates via propertyId?
<pre>
await properties.findOne({
where: { id },
include: [{
model: model.Unit, as: 'unit',
attributes: ['id'],
include: [{
model: model.Leases, as: 'leases',
attribute: ['id'],
include: [{ model: model.LeaseRates, as: 'leaserates' }]
}]
}]
})
</pre>

Multiple Sequelize Associations

I have a few associations between models like so:
Patient.hasMany(Transaction, {
as: 'transactions',
foreignKey: 'patient_id',
sourceKey: 'id'
});
Transaction.belongsTo(Patient, {
as: 'patient',
foreignKey: 'patient_id',
targetKey: 'id'
});
Transaction.hasMany(Transaction, {
as: 'transactions',
foreignKey: 'item_to_pay',
sourceKey: 'id'
});
I'm writing a query to get a list of transactions that belong to a patient and include the models associated with them:
Transaction.findAll({
where: {
patient_id: 1
},
include: [{
model: Patient,
as: 'patient',
attributes: ['first_name']
}, {
model: Transaction,
as: 'transactions',
include: [{
model: Patient,
as: 'patient',
attributes: ['first_name']
}]
}],
});
However when the result returns, it does not include the second nested patient model as I expect it to.
I've also tried writing a different query to see if I can get the desired result:
Transaction.findAll({
where: {
patient_id: 1
},
include: [{
model: Transaction,
as: 'transactions',
include: [{
model: Patient,
as: 'patient',
attributes: ['first_name']
}]
}],
});
But this query errors out and returns 'Unknown column 'patient.id' in field list'.
Does anyone see something wrong with my query or associations? Is there something I'm not understanding about the associations here?
I ended up changing my original query since I couldn't figure it out at the time. I stumbled into the same issue recently and realized the issue came from how I named my associations. I named the transaction.hasMany association as transactions which ended up confusing MySQL with the query that was generated because one of the tables is named transactions.
TLDR, don't name your associations the same name as any of your table names.

Sequelize - query with or operator and model association

With Sequelize, I have two models with many to many association : User and Category.
I want to get all categories that belongs to the current user, and also categories with a certain property, but I don't understand how, with only one query...
I'm using the Op.or operator, according to the documentation, and the $Model.attribute$ syntax for associated model (seen here).
let categories = await models.category.findAll({
where: {
[Op.or]: [
{ someCategoryProperty: true },
{ '$User.id$': req.currentUser.id },
],
},
include: [{
model: models.user,
as: 'User',
}],
});
The operator works if I add 2 conditions about the Category model, but how to add a condition on the association ?
I finally found the tips :
Actually, $Model.attribute$ wasn't the good pattern, $database_table_name.attribute$ is the good one.
With the '$..$' syntax, we must use the database table name, and not the model.
If my model is called user, Sequelize set the database name users !
So this code works :
let categories = await models.category.findAll({
where: {
[Op.or]: [
{ someCategoryProperty: true },
{ '$users.id$': req.currentUser.id },
],
},
include: [{
model: models.user,
}],
});
Thanks

in sequelize is it possible to paginate the Nested request using Nested eager loading?

I'm using the Nested eager loading funcionality, this is the sequelize example:
User.findAll({
include: [{
model: Tool,
as: 'Instruments',
include: [{
model: Teacher,
where: {
school: "Woodstock Music School"
},
required: false
}]
}]
}).then(function(users) {
/* ... */
})
Imagine you want to do an endpoint 'summary' and you want to include the Teacher model, but only the first three results
It is possible using only the Nested eager loading?
Sequelize provides a way to achieve this purpose?
After trying many things, I came to the conclusion that it can not do directly.
You can use limit and offset with teacher model
User.findAll({
include: [{
model: Tool,
as: 'Instruments',
include: [{
model: Teacher,
where: {
school: "Woodstock Music School"
},
limit: 3,
required: false
}
]
}
]
}).then(function (users) {
/* ... */
})

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