Sequelize multiple包含错误的连接查询

时间:2017-10-02 22:29:48

标签: mysql node.js sequelize.js

在我的域模型中,我有以下三种模型:

var challenge = sequelize.define('Challenge', {
    challengeId: {
        field: 'challenge_id',
        type: DataTypes.INTEGER,
        primaryKey: true,
        allowNull: false,
        autoIncrement: true,
        unique: true
    },
    ownerId: {
        type: DataTypes.INTEGER,
        references: { model: 'USER', key: 'user_id'},
        allowNull: false
    },
    description: {
        field: 'description',
        type: DataTypes.TEXT,
        allowNull: false
    }
};

challenge.belongsTo(models.User, {foreignKey: 'ownerId'});
challenge.hasMany(models.Idea, {foreignKey: 'challengeId'});

var idea = sequelize.define('Idea', {
  ideaId: {
    field: 'idea_id',
    type: DataTypes.INTEGER,
    primaryKey: true,
    allowNull: false,
    autoIncrement: true,
    unique: true
  },
  challengeId: {
    field: 'challenge_id',
    type: DataTypes.INTEGER,
    references: { model: 'CHALLENGE', key: 'challenge_id'},
    allowNull: true
  },
  description: {
    field: 'description',
    type: DataTypes.STRING(600),
    allowNull: false
  }
};
idea.belongsTo(models.Challenge, {foreignKey: 'challengeId'});

var user = sequelize.define('User', {
  userId: {
    field: 'user_id',
    type: DataTypes.INTEGER,
    primaryKey: true,
    autoIncrement: true,
    unique: true
  },
  name: {
    field: 'name',
    type: DataTypes.STRING,
    allowNull: false
  }
}
user.hasMany(models.Challenge, {foreignKey: 'ownerId'});

这表示一个简单的域模型,其中挑战由特定用户拥有。一个想法与一个或零个挑战相关联。

现在,我想搜索所有挑战,并添加一个与该挑战相关的想法数量。这个查询是我工作的,但是一旦我也想要包含用户信息,生成的SQL中的连接就不正确了。

要查询挑战并获得一些想法,我会这样做:

models.Challenge.findAll({
   attributes: ["Challenge.*", [models.sequelize.fn('COUNT', models.sequelize.col('Ideas.idea_id')), 'IdeaCount']],
   include: [{
      model: models.Idea,
      attributes: []
   }],
   group: ["Challenge.challenge_id"],
   order: [['count', 'ASC']]
}).then(function (rows) {
   console.log(rows)
 });

执行正确的SQL查询:

SELECT "Challenge"."challenge_id" AS "challengeId", 
      "Challenge".*, 
       COUNT("Ideas"."idea_id")   AS "IdeaCount" 
FROM   "CHALLENGE" AS "Challenge" 
       LEFT OUTER JOIN "IDEA" AS "Ideas" 
                    ON "Challenge"."challenge_id" = "Ideas"."challenge_id" 
WHERE  "Challenge"."company_id" = 1 
GROUP  BY "Challenge"."challenge_id" 
ORDER  BY "createdAt" DESC; 

现在,当我想要包含来自挑战创建者的信息时,我得到了错误的SQL。

models.Challenge.findAll({
   attributes: ["Challenge.*", [models.sequelize.fn('COUNT', models.sequelize.col('Ideas.idea_id')), 'IdeaCount']],
   include: [{
      model: models.Idea,
      attributes: []
   },
   {
      model: models.User,
      attributes: ["userId", "name"]
   }],
   group: ["Challenge.challenge_id"],
   order: [['count', 'ASC']]
}).then(function (rows) {
   console.log(rows)
 });

这导致以下SQL:

SELECT "Challenge".*, 
    COUNT("Ideas"."idea_id") AS "IdeaCount", 
       "User".*
FROM   "CHALLENGE" AS "Challenge" 
       LEFT OUTER JOIN "IDEA" AS "Ideas" 
                    ON "Challenge"."challenge_id" = "Ideas"."challenge_id" 
       INNER JOIN "USER" AS "User" 
               ON "Challenge"."ownerId" = "User"."user_id" 
       LEFT OUTER JOIN ("USER_ROLE" AS "User.Roles.USER_ROLE" 
                        INNER JOIN "ROLE" AS "User.Roles" 
                                ON "User.Roles"."role_id" = 
                                   "User.Roles.USER_ROLE"."feature_id") 
                    ON "User"."user_id" = "User.Roles.USER_ROLE"."user_id" 
WHERE  "Challenge"."company_id" = 1 
GROUP  BY "Challenge"."challenge_id" 
LIMIT  20;

相反,我需要这样的SQL查询:

SELECT "Challenge".*, 
   "User"."user_id", 
   "User"."firstname", 
   "User"."lastname" 
FROM   (SELECT "Challenge".*, 
               COUNT("Ideas"."idea_id") AS "IdeaCount" 
        FROM   "CHALLENGE" AS "Challenge" 
               LEFT OUTER JOIN "IDEA" AS "Ideas" 
                            ON "Challenge"."challenge_id" = 
                               "Ideas"."challenge_id" 
        WHERE  "Challenge"."company_id" = 1 
        GROUP  BY "Challenge"."challenge_id") AS "Challenge" 
       LEFT OUTER JOIN "USER" AS "User" 
                    ON "User"."user_id" = "Challenge"."ownerId" 
ORDER  BY "createdAt" DESC 
LIMIT  20; 

似乎sequelize将用户的左外连接放在与用于计算关联的级别相同的级别上。相反,用户信息的连接应该在它之外发生。是否有可能以这样的方式影响sequelize,就像在上面描述的SQL语句中那样单独完成此连接?

0 个答案:

没有答案