Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to count a group by query in NodeJS Sequelize

Tags:

In Rails I can perform a simple ORM query for the number of Likes a model has:

    @records = Model         .select( 'model.*' )         .select( 'count(likes.*) as likes_count' )         .joins( 'LEFT JOIN likes ON model.id = likes.model_id' )         .group( 'model.id' ) 

This generates the query:

SELECT  models.*, count(likes.*) as likes_count FROM "models" JOIN likes ON models.id = likes.model_id GROUP BY models.id 

In Node Sequelize, any attempt at doing something similar fails:

return Model.findAll({     group: [ '"Model".id' ],     attributes: ['id', [Sequelize.fn('count', Sequelize.col('"Likes".id')), 'likes_count']],     include: [{ attributes: [], model: Like }], }); 

This generates the query:

SELECT     Model.id,     count(Likes.id) AS likes_count,     Likes.id AS Likes.id           # Bad! FROM Models AS Model LEFT OUTER JOIN Likes     AS Likes     ON Model.id = Likes.model_id GROUP BY Model.id; 

Which generates the error:

column "Likes.id" must appear in the GROUP BY clause or be used in an aggregate function 

It's erroneously selecting likes.id, and I have no idea why, nor how to get rid of it.

like image 435
Andy Ray Avatar asked Apr 25 '15 18:04

Andy Ray


People also ask

How do you count a group by Sequelize?

Sequelize group by with aggregate functions const users = User. findAll({ attributes: [ "firstName", [sequelize. fn("COUNT", sequelize. col("isActive")), "count_isActive"], ], group: "firstName", });

How do you query in Sequelize?

As there are often use cases in which it is just easier to execute raw / already prepared SQL queries, you can use the sequelize. query method. By default the function will return two arguments - a results array, and an object containing metadata (such as amount of affected rows, etc).

How do you count distinct values in Sequelize?

count , you can just add any kind of aggregate function arguments supported by MYSQL to your options object. The following code will give you the amount of different values in MyModel 's someColumn : MyModel. count({distinct: 'someColumn', where: {...}}) .


2 Answers

This sequelize github issue looks totally like your case:

User.findAll({   attributes: ['User.*', 'Post.*', [sequelize.fn('COUNT', 'Post.id'), 'PostCount']],   include: [Post] }); 
like image 82
Evgeniy Chekan Avatar answered Sep 20 '22 09:09

Evgeniy Chekan


To resolve this problem we Need to upgrade to latest version of sequelize and include raw = true, Here is How I had done after lot of iteration and off-course googling.

 getUserProjectCount: function (req, res) {         Project.findAll(             {                 attributes: ['User.username', [sequelize.fn('COUNT', sequelize.col('Project.id')), 'ProjectCount']],                 include: [                     {                         model: User,                         attributes: [],                         include: []                     }                 ],                 group: ['User.username'],                 raw:true             }         ).then(function (projects) {             res.send(projects);         });     } 

where my reference models are

//user var User = sequelize.define("User", {     username: Sequelize.STRING,     password: Sequelize.STRING });  //project var Project = sequelize.define("Project", {     name: Sequelize.STRING,     UserId:{          type:Sequelize.INTEGER,          references: {                  model: User,                   key: "id"          }     } });  Project.belongsTo(User); User.hasMany(Project); 

after migration ORM create 'Users' & 'Projects' table into my postgres server. Here is SQL Query by ORM

SELECT    "User"."username", COUNT("Project"."id") AS "ProjectCount"   FROM      "Projects" AS "Project"      LEFT OUTER JOIN "Users" AS "User" ON "Project"."UserId" = "User"."id"   GROUP BY     "User"."username"; 
like image 25
sangram Avatar answered Sep 21 '22 09:09

sangram