Reputation: 112
I'm currently using PostgreSQL and Sequelize.js to query some data. When I'm using sequelize.query(), it only returns one row data but when I enter it through pgAdmin it works as expected.
Here is the code I use in sequelize.query().
SELECT table2.student_id,
s.canvasser_name,
l.level_name,
table2.total_score
FROM (SELECT table1.student_id,
sum(table1.max_score) total_score
FROM (SELECT sq.student_id,
max(sq.score) max_score
FROM public.student_quiz sq
GROUP BY sq.quiz_id, sq.student_id) table1
GROUP BY table1.student_id) table2
INNER JOIN public.student s
ON s.id = table2.student_id
INNER JOIN public.level l
ON l.id = s.level_id
ORDER BY table2.total_score DESC
LIMIT 10;
And here is the nodejs code
const getRank = (option, logs = {}) => new Promise(async (resolve, reject) => {
try {
let { offset, limit } = option;
if (!limit) limit = 10;
const result = await sequelize.query(
`SELECT table2.student_id,
s.canvasser_name,
l.level_name,
table2.total_score
FROM (SELECT table1.student_id,
sum(table1.max_score) total_score
FROM (SELECT sq.student_id,
max(sq.score) max_score
FROM public.student_quiz sq
GROUP BY sq.quiz_id, sq.student_id) table1
GROUP BY table1.student_id) table2
INNER JOIN public.student s
ON s.id = table2.student_id
INNER JOIN public.level l
ON l.id = s.level_id
ORDER BY table2.total_score DESC
LIMIT 10;`,
{ plain: true }
);
return resolve(result);
} catch (error) {
let customErr = error;
if (!error.code) customErr = Helpers.customErrCode(error, null, undefinedError);
logger.error(logs);
return reject(customErr);
}
});
And here is the code that consume the function above
const getRankController = async (req, res) => {
try {
const { offset, limit } = req.query;
const result = await getRank({ offset, limit });
if (result.length < 1) {
return Helpers.response(res, {
success: false,
message: 'cannot get score list'
}, 404);
}
return Helpers.response(res, {
success: true,
result
});
} catch (error) {
return Helpers.error(res, error);
}
};
In the meantime, I'm trying another approach using the sequelize built in function, here is the code.
const getRank = (
option,
logs = {}
) => new Promise(async (resolve, reject) => {
try {
// eslint-disable-next-line prefer-const
let { offset, limit } = option;
if (!limit) limit = 10;
const result2 = await StudentQuiz.findAll({
attributes: ['studentId', [sequelize.fn('sum', sequelize.fn('max', sequelize.col('score'))), 'totalPrice'], 'quizId'],
group: 'studentId',
include: [
{
model: Student,
include: [{
model: Level
}],
},
],
offset,
limit
});
return resolve(result2);
} catch (error) {
let customErr = error;
if (!error.code) customErr = Helpers.customErrCode(error, null, undefinedError);
logger.error(logs);
return reject(customErr);
}
});
This one does not work since it is nested function, I kinda don't get it how to reproduce it.
I've tried to do some simple query like SELECT * FROM table and it returns one row, and then I've found out that I need to add "public" to table name so it became SELECT * FROM public.table and it works out. Well, until I'm trying the code in the second code block.
Any answer or advice will be appreciated, thank you.
Upvotes: 1
Views: 7867
Reputation: 21
For those still having issues with this, what worked for me was to use
type: Sequelize.QueryTypes.RAW
instead of
type: Sequelize.QueryTypes.SELECT
Full query:
const result = await sequelize.query(
`SELECT table2.student_id,
s.canvasser_name,
l.level_name,
table2.total_score
FROM (SELECT table1.student_id,
sum(table1.max_score) total_score
FROM (SELECT sq.student_id,
max(sq.score) max_score
FROM public.student_quiz sq
GROUP BY sq.quiz_id, sq.student_id) table1
GROUP BY table1.student_id) table2
INNER JOIN public.student s
ON s.id = table2.student_id
INNER JOIN public.level l
ON l.id = s.level_id
ORDER BY table2.total_score DESC
LIMIT 10;`,
{
type: Sequelize.QueryTypes.RAW
}
);
Upvotes: 1
Reputation: 22758
I suppose you need to indicate a query type and remove plain: true
option like this:
const result = await sequelize.query(
`SELECT table2.student_id,
s.canvasser_name,
l.level_name,
table2.total_score
FROM (SELECT table1.student_id,
sum(table1.max_score) total_score
FROM (SELECT sq.student_id,
max(sq.score) max_score
FROM public.student_quiz sq
GROUP BY sq.quiz_id, sq.student_id) table1
GROUP BY table1.student_id) table2
INNER JOIN public.student s
ON s.id = table2.student_id
INNER JOIN public.level l
ON l.id = s.level_id
ORDER BY table2.total_score DESC
LIMIT 10;`,
{
type: Sequelize.QueryTypes.SELECT
}
);
From Sequelize documentation:
options.plain - Sets the query type to SELECT and return a single row
Upvotes: 3