I have two tables, locations
and sensors
. Each entry in sensors
has a foreign key pointing to locations
. Using Sequelize, how do I get all entries from locations
and total count of entries in sensors
that are associated with each entry in locations
?
Raw SQL:
SELECT `locations`.*, COUNT(`sensors`.`id`) AS `sensorCount` FROM `locations` JOIN `sensors` ON `sensors`.`location`=`locations`.`id`; GROUP BY `locations`.`id`;
Models:
module.exports = function(sequelize, DataTypes) { var Location = sequelize.define("Location", { id: { type: DataTypes.INTEGER.UNSIGNED, primaryKey: true }, name: DataTypes.STRING(255) }, { classMethods: { associate: function(models) { Location.hasMany(models.Sensor, { foreignKey: "location" }); } } }); return Location; }; module.exports = function(sequelize, DataTypes) { var Sensor = sequelize.define("Sensor", { id: { type: DataTypes.INTEGER.UNSIGNED, primaryKey: true }, name: DataTypes.STRING(255), type: { type: DataTypes.INTEGER.UNSIGNED, references: { model: "sensor_types", key: "id" } }, location: { type: DataTypes.INTEGER.UNSIGNED, references: { model: "locations", key: "id" } } }, { classMethods: { associate: function(models) { Sensor.belongsTo(models.Location, { foreignKey: "location" }); Sensor.belongsTo(models.SensorType, { foreignKey: "type" }); } } }); return Sensor; };
In Sequelize, you can add the group option in your query method findAll() to add the GROUP BY clause to the generated SQL query. Now you want to select all firstName values and group any duplicate values of the column. Here's the code for calling the findAll() method on the model: const users = await User.
Sequelize uses the lower case model name as the alias for your table name in your generated SQL query. If you have a model Commit and a table commits , for example, the fully qualified column name should be sequelize. col('commit.id') .
Sequelize where option accepts an object describing the WHERE clause to add to your generated SQL query. For a WHERE clause with a simple condition, you can add a single property to the where object. The property name will be the column name and the property value will be the value you use to filter the query.
Use findAll()
with include()
and sequelize.fn()
for the COUNT
:
Location.findAll({ attributes: { include: [[Sequelize.fn("COUNT", Sequelize.col("sensors.id")), "sensorCount"]] }, include: [{ model: Sensor, attributes: [] }] });
Or, you may need to add a group
as well:
Location.findAll({ attributes: { include: [[Sequelize.fn("COUNT", Sequelize.col("sensors.id")), "sensorCount"]] }, include: [{ model: Sensor, attributes: [] }], group: ['Location.id'] })
For Counting associated entries with Sequelize
Location.findAll({ attributes: { include: [[Sequelize.fn('COUNT', Sequelize.col('sensors.location')), 'sensorCounts']] }, // Sequelize.col() should contain a attribute which is referenced with parent table and whose rows needs to be counted include: [{ model: Sensor, attributes: [] }], group: ['sensors.location'] // groupBy is necessary else it will generate only 1 record with all rows count })
Note :
Some how, this query generates a error like sensors.location is not exists in field list. This occur because of subQuery which is formed by above sequelize query.
So solution for this is to provide subQuery: false like example
Location.findAll({ subQuery: false, attributes: { include: [[Sequelize.fn('COUNT', Sequelize.col('sensors.location')), 'sensorCounts']] }, include: [{ model: Sensor, attributes: [] }], group: ['sensors.location'] })
Note: **Sometime this could also generate a error bcz of mysql configuration which by default contains only-full-group-by in sqlMode, which needs to be removed for proper working.
The error will look like this..**
Error : Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'db.table.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
So to resolve this error follow this answer
SELECT list is not in GROUP BY clause and contains nonaggregated column .... incompatible with sql_mode=only_full_group_by
Now this will successfully generate all associated counts
Hope this will help you or somebody else!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With