场景回顾
数据库:Mysql5
Sequelize版本:5.21.5
我们有两个表,分别为 用户表(user)和文章表(article),建立Sequelize模型如下
User.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | module.exports = function (sequelize, DataTypes) { return sequelize.define('user', { id: { // 编号 type: DataTypes.BIGINT, primaryKey: true, autoIncrement: true }, name: { // 昵称 type: DataTypes.STRING(32), defaultValue: '' }, avatar: { // 头像 type: DataTypes.STRING(1000), defaultValue: '' }, }); }; |
Article.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | module.exports = function (sequelize, DataTypes) { return sequelize.define('article', { id: { // 编号 type: DataTypes.BIGINT, primaryKey: true, autoIncrement: true }, title: { // 标题 type: DataTypes.STRING(32), defaultValue: '' }, user_id: { // 玩家ID type: DataTypes.STRING(1000), defaultValue: '', references: { model: 'User', key: 'id' }, }, }); }; |
模型关系如下:
association.js
1 2 | User.hasMany(Article, {foreignKey: 'user_id', as:'article'}); Article.belongsTo(User, {foreignKey: 'user_id'}); |
我们使用findAndCountAll进行分页查询User列表,如下:
1 2 3 4 5 6 | const page = 1, count = 20; const { count, rows } = await User.findAndCountAll({ offset: (page - 1) * count, limit: count, where: filters, }); |
生成对应的SQL语句如下
1 | SELECT `id`,`name`, `avatar` FROM `user` AS `user` LIMIT 0, 20; |
如果希望在用户列表显示该用户的文章数量,我们使用include进行关联查询,如下:
1 2 3 4 5 6 7 8 9 10 11 12 | const page = 1, count = 20; const { count, rows } = await User.findAndCountAll({ offset: (page - 1) * count, limit: count, attributes:['id', 'name', 'avatar', , [sequelize.fn('COUNT', sequelize.col('article.id')), 'article.count']] include:[{ model: Article, as: "article", attributes: [] }], group: ['user.id'] }); |
生成SQL语句如下
1 2 3 4 | SELECT `user`.* FROM (SELECT `user`.`name`, `user`.`avatar`, COUNT(`article`.`id`) AS `article.count` FROM `user` AS `user` WHERE GROUP BY `user`.`id` LIMIT 0, 20) AS `user` LEFT OUTER JOIN `article` AS `article` ON `user`.`id` = `article`.`user_id`; |
并且报错:Unknown column 'article.id' in 'field list'
加入没有进行分页查询,如下:
1 2 3 4 5 6 7 8 9 10 | const page = 1, count = 20; const { count, rows } = await User.findAndCountAll({ attributes:['id', 'name', 'avatar', , [sequelize.fn('COUNT', sequelize.col('article.id')), 'article.count']] include:[{ model: Article, as: "article", attributes: [] }], group: ['user.id'] }); |
生成的SQL语句
1 2 3 | SELECT `user`.`name`, `user`.`avatar`, COUNT(`article`.`id`) AS `article.count` FROM `user` AS `user` LEFT OUTER JOIN `article` AS `article` ON `user`.`id` = `article`.`user_id` GROUP BY `user`.`id`; |
这正是我们想要的,问题就在于分页查询。
其实我们只需要在include里面设置一下duplicating属性为false就可以了,如下
1 2 3 4 5 6 7 8 9 10 11 12 13 | const page = 1, count = 20; const { count, rows } = await User.findAndCountAll({ offset: (page - 1) * count, limit: count, attributes:['id', 'name', 'avatar', , [sequelize.fn('COUNT', sequelize.col('article.id')), 'article.count']] include:[{ model: Article, as: "article", duplicating:false, attributes: [] }], group: ['user.id'] }); |
得到的SQL语句
1 2 3 | SELECT `user`.`name`, `user`.`avatar`, COUNT(`article`.`id`) AS `article.count` FROM `user` AS `user` LEFT OUTER JOIN `article` AS `article` ON `user`.`id` = `article`.`user_id` GROUP BY `user`.`id` LIMIT 0, 20; |
大功告成!