Sequelize使用findAndCountAll、belongsTo、hasMany、include、count、sum、group進行多表關聯統計查詢問題小結

場景回顧

數據庫:Mysql5

Sequelize版本:5.21.5

我們有兩個表,分別爲 用戶表(user)和文章表(article),建立Sequelize模型如下

User.js

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

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

User.hasMany(Article, {foreignKey: 'user_id', as:'article'});
Article.belongsTo(User, {foreignKey: 'user_id'});

我們使用findAndCountAll進行分頁查詢User列表,如下:

const page = 1, count = 20;
const { count, rows } = await User.findAndCountAll({
      offset: (page - 1) * count,
      limit: count,
      where: filters,
    });

生成對應的SQL語句如下

SELECT `id`,`name`, `avatar` FROM `user` AS `user` LIMIT 0, 20;

如果希望在用戶列表顯示該用戶的文章數量,我們使用include進行關聯查詢,如下:

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語句如下

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'

加入沒有進行分頁查詢,如下:

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語句

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就可以了,如下

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語句

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;

大功告成!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章