how to set order on include aggregate function alias in sequelize? - node.js

Below is my code
export async function getMany(page: number, recordsPerPage: number, condition: any = {}, order: any, attributes: string[] = [], other: object = {}) {
try {
let { count, rows }: any = await User.findAndCountAll({
attributes: {
include: [[sequelize.literal('(SELECT SUM(reputation) FROM scores where scores.user_id = User.id)'), 'reputation']],
exclude: attributes,
},
where: condition,
distinct: true,
include: [
{
model: Skill,
as: 'skills',
attributes: ['skill'],
through: { attributes: [] },
},
],
order: order,
offset: page,
limit: recordsPerPage,
...other,
logging: console.log,
});
return { count, rows };
} catch (e) {
return false;
}
}
I want to set order by reputation field which is alias of sum function column. i want my data in highest to lowest reputation.

You can simply replace the order property with the given snippet. Worked for me.
order: [[sequelize.literal('table alias name goes here'), 'DESC']]

Related

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

Sequelize - Select on associated table

My problem:
I am creating an route which will return some informations about a group, it has an id, an user assigned and also has some documents. I just want to show how much documents exists, in SQL would be SELECT COUNT, but how can i do this in this in sequelize?
My code:
async list(req, res){
const docGroups = await DocGroup.findAll({
raw: true,
include: [{
model: User,
as: 'userAssigned'
},
{
model: Document,
as: 'Document'
}
]
}).then(groups => {
const result = groups.map(group => {
return Object.assign(
{},
{
id: group.id,
name: group.name,
userAssinged: group['userAssigned.firstName'],
docAmount: // I want to put documents' count here
}
)
})
console.log(groups)
})
}
What is printed in console.log(groups):
[
{
id: 1,
name: 'pleaseworks',
createdAt: 2020-06-10T02:38:11.531Z,
updatedAt: 2020-06-10T02:38:11.531Z,
'userAssigned.id': 1,
'userAssigned.firstName': 'Please',
'userAssigned.lastName': 'Works',
'userAssigned.email': 'pleaseworks#gmail.com',
'userAssigned.password': '$2a$08$3BA4I4dsaQ3lsHy342344b5P41v5eHWjwqv6dve28nSdqbGvhsdS',
'userAssigned.createdAt': 2020-06-10T02:37:29.062Z,
'userAssigned.updatedAt': 2020-06-10T02:37:29.062Z,
'userAssigned.groupId': null,
'Document.id': 2,
'Document.description': 'deowkdopewkdwe',
'Document.content': 'odepodkewokodwe',
'Document.groupId': 1,
'Document.createdAt': 2020-06-10T02:43:46.005Z,
'Document.updatedAt': 2020-06-10T02:43:46.005Z
}
]
If DocGroup has many Document try something like this:
{
model: Document,
attributes: [[sequelize.fn('COUNT', sequelize.col('id')), 'docAmount']]
as: 'Document'
}

Sequelize - ORDER BY count of associations

I have two models, Company and Employee. The association is like Company hasMany Employee. Employee belongsTo Company.
I have to list all the Companies ordered by count of associations it have in the descending order.
My function is like following,
function get() {
return Company.findAndCountAll({
where: { status: Active },
include: [
{
model: Employee,
as: 'employees'
}
],
}).then((companies) => {
return companies
})
}
What can I give in order so that I can get list of companies based on count of associations(Employees) in descending order.
Please help me out in this...
I have tried as below. but it is throwing error like invalid reference to FROM-clause entry for table companies.
function get() {
return Company.findAndCountAll({
where: { status: Active },
include: [
{
model: Employee,
as: 'employees'
}
],
attributes: [
[Sequelize.literal('(SELECT COUNT(*) FROM employees WHERE employees.company_id = companies.id)'), 'employeesCount']
],
order: [[Sequelize.literal('employeesCount'), 'DESC']],
}).then((companies) => {
return companies
})
}
where companies is the table name.
You can try this.
Please replace your fieldName with sortField
function get() {
return Company.findAndCountAll({
where: { status: Active },
include: [
{
model: Employee,
as: 'employees'
}
],
order: [[sortField, 'DESC']]
}).then((companies) => {
return companies
})
}

Sequelize: how to implement a search based on associated keywords?

I am looking to return all articles from the database associated with one or more keywords, but I am not sure there right way to go about this?
I am using Sequelize 3.x, with node.js 3.7.0.
The data model looks at follows:
const Article = sequelize.define('article', {
...
}
const Keyword = sequelize.define('keyword', {
name: Sequelize.STRING,
lang: Sequelize.STRING
}
const ArticleKeyword = sequelize.define('article_keyword', {
articleId: Sequelize.INTEGER,
keywordId: Sequelize.INTEGER
}
(Article).belongsToMany(
Keyword, { through: ArticleKeyword, as: 'keyword' });
(Keyword).belongsToMany(
Article { through: ArticleKeyword, as: 'article' });
Then the query I tried:
var keywordFilter;
if (req.body.keywords) {
var keywords = req.body.keywords);
if (typeof keywords === 'string') {
keywords = keywords.split(/ *, */);
}
keywordFilter = { name: { $in: keywords } };
}
Article.findAll({
where: {
deleted: false
},
include: [{
model: Keyword,
as: 'keywords',
where: keywordFilter,
attributes: ['name'],
through: {
attributes: []
}
}]
}).then(function(articles) {
...
});
The issue I am finding here is rather than selecting just the articles with the matching keywords it returns all the articles and then simply selects the keywords specified in the query for the results.
Can anyone suggest the right way to go about this?
Hi can you try passing
require:true
in the include block for inner join and check
Ref : https://stackoverflow.com/a/31680398/4583460

Sequelize ORM include model only if active = true

how can I findAll orders with id: 1 and include items only if this item has active = true? Otherwise there will be empty array...
Order.findAll({
where: { id: 1 },
include: [
{ model: Item, where: sequelize.and({'active' : true }) }
]
}).then(function(order) {
callback(null, order);
});
This shows me only orders where are some items with active = true. I wanted to show all orders with id: 1 and items as a sub-array ...
From Sequelize Tutorial:
Adding a where clause to the include automatically makes it required
The solution is this:
Order.findAll({
where: { id: 1 },
include: [
{ model: Item,
where: sequelize.and({'active' : true }),
required: false
}
]
}).then(function(order) {
callback(null, order);
});

Resources