使用Sequelize计算相关条目

Mik*_*koP 14 mysql node.js sequelize.js

我有两张桌子,locationssensors.每个条目sensors都有一个指向的外键locations.使用Sequelize,我如何获得与每个条目相关的所有条目locations和总条目数?sensorslocations

原始SQL:

SELECT 
    `locations`.*,
    COUNT(`sensors`.`id`) AS `sensorCount` 
FROM `locations` 
JOIN `sensors` ON `sensors`.`location`=`locations`.`id`;
GROUP BY `locations`.`id`;
Run Code Online (Sandbox Code Playgroud)

楷模:

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;
};
Run Code Online (Sandbox Code Playgroud)

ale*_*cxe 27

使用findAll()include()sequelize.fn()COUNT:

Location.findAll({
    attributes: { 
        include: [[Sequelize.fn("COUNT", Sequelize.col("sensors.id")), "sensorCount"]] 
    },
    include: [{
        model: Sensor, attributes: []
    }]
});
Run Code Online (Sandbox Code Playgroud)

或者,您可能还需要添加一个group:

Location.findAll({
    attributes: { 
        include: [[Sequelize.fn("COUNT", Sequelize.col("sensors.id")), "sensorCount"]] 
    },
    include: [{
        model: Sensor, attributes: []
    }],
    group: ['Location.id']
})
Run Code Online (Sandbox Code Playgroud)

  • 如果您应用限制,则无效 (2认同)

Ama*_*pta 10

用于使用 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
})
Run Code Online (Sandbox Code Playgroud)

笔记 :

不知怎的,这个查询生成了一个错误,比如sensors.location is not存在于字段列表中。发生这种情况是因为上面的后续查询形成的子查询。

所以解决方案是提供 subQuery: false 像示例

Location.findAll({
        subQuery: false,
        attributes: { 
            include: [[Sequelize.fn('COUNT', Sequelize.col('sensors.location')), 'sensorCounts']] 
        },
        include: [{
            model: Sensor, attributes: []
        }],
        group: ['sensors.location']
    })
Run Code Online (Sandbox Code Playgroud)

注意: **有时这也可能会生成 mysql 配置的错误 bcz,默认情况下,sqlMode 中仅包含 full-group-by,需要将其删除才能正常工作。

错误看起来像这样..**

错误:SELECT 列表的表达式 #1 不在 GROUP BY 子句中,并且包含非聚合列“db.table.id”,该列在功能上不依赖于 GROUP BY 子句中的列;这与 sql_mode=only_full_group_by 不兼容

因此,要解决此错误,请遵循此答案

SELECT 列表不在 GROUP BY 子句中并且包含非聚合列....与 sql_mode=only_full_group_by 不兼容

现在这将成功生成所有关联的计数

希望这会对您或其他人有所帮助!


Ari*_*man 5

Location.findAll({
        attributes: { 
            include: [[Sequelize.fn("COUNT", Sequelize.col("sensors.id")), "sensorCount"]] 
        },
        include: [{
            model: Sensor, attributes: []
        }]
    });
Run Code Online (Sandbox Code Playgroud)

它有效。但是当我添加“限制”时,出现错误:传感器未定义

  • 您可以在查询选项中尝试 subQuery: false 。 (3认同)