【问题标题】:Node.js sequelize associations includeNode.js sequelize 关联包括
【发布时间】:2015-07-27 16:04:02
【问题描述】:

这是我查询模型时的错误吗(短版本):

var User = db.define('User', {
  login: Sequelize.STRING(16),
  password: Sequelize.STRING,
});

var Group = db.define('Group', {
  name: Sequelize.STRING,
});

var GroupSection = db.define('GroupSection', {
  name: Sequelize.STRING,
});

Group.belongsTo(GroupSection, { as: 'GroupSection',
  foreignKey: 'GroupSectionId' });
GroupSection.hasMany(Group, { as: 'Groups', foreignKey: 'GroupSectionId' });

Group.belongsTo(Group, { as: 'ParentGroup', foreignKey: 'ParentGroupId' });
Group.hasMany(Group, { as: 'ChildGroups', foreignKey: 'ParentGroupId' });

User.belongsToMany(Group, { as: 'Groups', through: 'UsersToGroups' });
Group.belongsToMany(User, { as: 'Users', through: 'UsersToGroups' });

此查询工作正常(注意包含在包含内):

User.findOne({
    include: [{
      model: Group,
      as: 'Groups',
      where: {
        name: 'Group name',
      },
      include: [{
        model: GroupSection,
        as: 'GroupSection',
      }]
    }]
  }).then(function(user) {
    // some code
  })

但是这个查询给出了错误(只有“where”参数添加到内部包含):

User.findOne({
    include: [{
      model: Group,
      as: 'Groups',
      where: {
        name: 'Group name',
      },
      include: [{
        model: GroupSection,
        as: 'GroupSection',
        where: {
          name: 'Some section name',
        },
      }]
    }]
  }).then(function(user) {
    // some code
  })

上面的代码给出了错误:
未处理的拒绝 SequelizeDatabaseError:缺少表“组”的 FROM 子句条目

我检查了它生成的 SQL 代码,我可以通过不使用内部 where 子句来解决这个问题,而是在 where 子句中添加一些原始代码。我该怎么做这样的事情:

User.findOne({
  include: [{
    model: Group,
    as: 'Groups',
    where: {
      name: 'Admin',
      $somethin_i_need$: 'raw sql goes here',
    },
    include: [{
      model: GroupSection,
      as: 'GroupSection',
    }]
  }]
}).then(function(user) {
  // some code
})

添加(代码被某个在线服务美化了):

在没有内部 where 的情况下生成的代码(工作正常):

SELECT "User".*,
       "groups"."id"                      AS "Groups.id",
       "groups"."name"                    AS "Groups.name",
       "groups"."createdat"               AS "Groups.createdAt",
       "groups"."updatedat"               AS "Groups.updatedAt",
       "groups"."groupsectionid"          AS "Groups.GroupSectionId",
       "groups"."parentgroupid"           AS "Groups.ParentGroupId",
       "Groups.UsersToGroups"."createdat" AS "Groups.UsersToGroups.createdAt",
       "Groups.UsersToGroups"."updatedat" AS "Groups.UsersToGroups.updatedAt",
       "Groups.UsersToGroups"."groupid"   AS "Groups.UsersToGroups.GroupId",
       "Groups.UsersToGroups"."userid"    AS "Groups.UsersToGroups.UserId",
       "Groups.GroupSection"."id"         AS "Groups.GroupSection.id",
       "Groups.GroupSection"."name"       AS "Groups.GroupSection.name",
       "Groups.GroupSection"."createdat"  AS "Groups.GroupSection.createdAt", 
       "Groups.GroupSection"."updatedat"  AS "Groups.GroupSection.updatedAt"
FROM   (SELECT "User"."id",
               "User"."login",
               "User"."password",
               "User"."createdat",
               "User"."updatedat"
        FROM   "users" AS "User"
        WHERE  (SELECT "userstogroups"."groupid"
                FROM   "userstogroups" AS "UsersToGroups"
                       INNER JOIN "groups" AS "Group"
                               ON "userstogroups"."groupid" = "Group"."id"
                WHERE  ( "User"."id" = "userstogroups"."userid" )
                LIMIT  1) IS NOT NULL
        LIMIT  1) AS "User"
       INNER JOIN ("userstogroups" AS "Groups.UsersToGroups"
                   INNER JOIN "groups" AS "Groups"
                           ON "groups"."id" = "Groups.UsersToGroups"."groupid")
               ON "User"."id" = "Groups.UsersToGroups"."userid"
                  AND "groups"."name" = 'Group name'
       LEFT OUTER JOIN "groupsections" AS "Groups.GroupSection"
                    ON "groups"."groupsectionid" = "Groups.GroupSection"."id";

用内部where生成的代码(生成错误的sql):

SELECT "User".*, 
       "groups"."id"                      AS "Groups.id", 
       "groups"."name"                    AS "Groups.name", 
       "groups"."createdat"               AS "Groups.createdAt", 
       "groups"."updatedat"               AS "Groups.updatedAt", 
       "groups"."groupsectionid"          AS "Groups.GroupSectionId", 
       "groups"."parentgroupid"           AS "Groups.ParentGroupId", 
       "Groups.UsersToGroups"."createdat" AS "Groups.UsersToGroups.createdAt", 
       "Groups.UsersToGroups"."updatedat" AS "Groups.UsersToGroups.updatedAt", 
       "Groups.UsersToGroups"."groupid"   AS "Groups.UsersToGroups.GroupId", 
       "Groups.UsersToGroups"."userid"    AS "Groups.UsersToGroups.UserId" 
FROM   (SELECT "User"."id", 
               "User"."login", 
               "User"."password", 
               "User"."createdat", 
               "User"."updatedat", 
               "Groups.GroupSection"."id"        AS "Groups.GroupSection.id", 
               "Groups.GroupSection"."name"      AS "Groups.GroupSection.name", 
               "Groups.GroupSection"."createdat" AS 
               "Groups.GroupSection.createdAt", 
               "Groups.GroupSection"."updatedat" AS 
               "Groups.GroupSection.updatedAt" 
        FROM   "users" AS "User" 
               INNER JOIN "groupsections" AS "Groups.GroupSection" 
                       ON "groups"."GroupSectionId" = "Groups.GroupSection"."id" 
                          AND "Groups.GroupSection"."name" = 'Section name' 
        WHERE  (SELECT "userstogroups"."groupid" 
                FROM   "userstogroups" AS "UsersToGroups" 
                       INNER JOIN "groups" AS "Group" 
                               ON "userstogroups"."groupid" = "Group"."id" 
                WHERE  ( "User"."id" = "userstogroups"."userid" ) 
                LIMIT  1) IS NOT NULL 
        LIMIT  1) AS "User" 
       INNER JOIN ("userstogroups" AS "Groups.UsersToGroups" 
                   INNER JOIN "groups" AS "Groups" 
                           ON "groups"."id" = "Groups.UsersToGroups"."groupid") 
               ON "User"."id" = "Groups.UsersToGroups"."userid" 
                  AND "groups"."name" = 'Group name'; 

说明真正需要什么

我不需要具有没有组或没有组的用户的记录等等。例如。在找到该用户之后将组附加到用户(并且决定它将进入结果)。这意味着我需要这个“where”子句位于用户模型上(与对象中的第一个“包含”键处于同一级别),但它需要检查多个表(我的真实数据库更复杂) .

【问题讨论】:

  • 可以分享一下生成的SQL吗?

标签: node.js sequelize.js


【解决方案1】:

我有类似的错误。 我没有为我的问题找到任何答案。 但我让它工作。我不知道它是否也适合你,但我写了我的解决方案。

请尝试在最后包含required:false 属性:

User.findOne({
    include: [{
      model: Group,
      as: 'Groups',
      where: {
        name: 'Group name',
      },
      include: [{
        model: GroupSection,
        as: 'GroupSection',
        required: false,
        where: {
          name: 'Some section name',
        },
      }]
    }]
  }).then(function(user) {
    // some code
  })

为什么这对我有用,也应该对你有用? 当您在最后一个子查询中省略 where 时,默认情况下 required 的值为 false。当您设置where 时,默认情况下required 的值为true。这引导我找到了这个解决方案。

来自docs作为确认:

[options.include[].where] Where 子句应用于子 楷模。请注意,这会将急切负载转换为内部连接, 除非你明确设置 required: false

[options.include[].required] 如果为真,则转换为内部 join,这意味着只有当父模型有 任何匹配的孩子。如果设置了 include.where 则为 true,否则为 false。

简而言之,内部连接存在一些问题。当你设置where 属性时,这个添加子查询作为内连接,除非你设置required:false

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 2018-05-15
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    相关资源
    最近更新 更多