我有两个表,locations
和sensors
。 sensors
中的每个条目都有一个指向locations
的外键。使用Sequelize,如何获取locations
中的所有条目以及sensors
中与locations
中每个条目相关联的条目总数?
原始SQL:
SELECT
`locations`.*,
COUNT(`sensors`.`id`) AS `sensorCount`
FROM `locations`
JOIN `sensors` ON `sensors`.`location`=`locations`.`id`;
GROUP BY `locations`.`id`;
型号:
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;
};
答案 0 :(得分:22)
findAll()
使用include()
,sequelize.fn()
使用COUNT
:
Location.findAll({
attributes: {
include: [[Sequelize.fn("COUNT", Sequelize.col("sensors.id")), "sensorCount"]]
},
include: [{
model: Sensor, attributes: []
}]
});
或者,您可能还需要添加group
:
Location.findAll({
attributes: {
include: [[Sequelize.fn("COUNT", Sequelize.col("sensors.id")), "sensorCount"]]
},
include: [{
model: Sensor, attributes: []
}],
group: ['Location.id']
})
答案 1 :(得分:2)
用于使用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
})
注意:
某种程度上,此查询会生成类似 sensors.location的错误,该查询在字段列表中不存在。发生这种情况是由于上述续集查询形成了subQuery。
因此,解决方案是提供subQuery:如示例一样为false
Location.findAll({
subQuery: false,
attributes: {
include: [[Sequelize.fn('COUNT', Sequelize.col('sensors.location')), 'sensorCounts']]
},
include: [{
model: Sensor, attributes: []
}],
group: ['sensors.location']
})
注意: **有时这还会生成mysql配置错误bcz,默认情况下,该配置在sqlMode中仅包含full-group-by,需要将其删除才能正常工作。
错误看起来像这样。.**
错误:SELECT列表的表达式#1不在GROUP BY子句中,并且包含未聚合的列'db.table.id',该列在功能上不依赖于GROUP BY子句中的列;这与sql_mode = only_full_group_by
不兼容因此,要解决此错误,请遵循以下答案
现在,这将成功生成所有关联的计数
希望这对您或其他人有帮助!
答案 2 :(得分:1)
Location.findAll({
attributes: {
include: [[Sequelize.fn("COUNT", Sequelize.col("sensors.id")), "sensorCount"]]
},
include: [{
model: Sensor, attributes: []
}]
});
它有效。但是当我添加"限制"时,我收到错误:传感器未定义
答案 3 :(得分:0)
如何为它定义一个数据库视图,然后为该视图定义一个模型?只要您需要传感器的数量,您就可以获取与查询中包含的视图的关系。这样代码可能看起来更干净,但我不知道是否会有性能成本。其他人可能会回答...
CREATE OR REPLACE VIEW view_location_sensors_count AS
select "locations".id as "locationId", count("sensors".id) as "locationSensorsCount"
from locations
left outer join sensors on sensors."locationId" = location.id
group by location.id
为视图定义模型时,删除 id 属性并将 locationId 设置为主键。 您的模型可能如下所示:
const { Model, DataTypes } = require('sequelize')
const attributes = {
locationID: {
type: DataTypes.UUIDV4, // Or whatever data type is your location ID
primaryKey: true,
unique: true
},
locationSensorsCount: DataTypes.INTEGER
}
const options = {
paranoid: false,
modelName: 'ViewLocationSensorsCount',
tableName: 'view_location_sensors_count',
timestamps: false
}
/**
* This is only a database view. It is not an actual table, so
* DO NOT ATTEMPT insert, update or delete statements on this model
*/
class ViewLocationSensorsCount extends Model {
static associate(models) {
ViewLocationSensorsCount.removeAttribute('id')
ViewLocationSensorsCount.belongsTo(models.Location, { as:'location', foreignKey: 'locationID' })
}
static init(sequelize) {
this.sequelize = sequelize
return super.init(attributes, {...options, sequelize})
}
}
module.exports = ViewLocationSensorsCount
最后,在 Location 模型中,您设置了与 Sensor 模型的 hasOne 关系。