【问题标题】:Sequelize join two columns of one table to the same column of another tableSequelize将一张表的两列连接到另一张表的同一列
【发布时间】:2021-03-18 00:16:13
【问题描述】:

我有一个表 RelationuserId1userId2 它基本上存储了两个用户之间的关系,userId1userId2 是此处从 User 表 id (PK) 列引用的外键。

   id: {
        type: DataTypes.INTEGER.UNSIGNED,
        autoIncrement: true,
        primaryKey: true,
        allowNull: false,
    },
    userId1: {
        type: DataTypes.INTEGER.UNSIGNED,
        allowNull: false,
    },
    userId2: {
        type: DataTypes.INTEGER.UNSIGNED,
        allowNull: false,
    },
    status: {
        type: DataTypes.ENUM,
    },

然后是另一个表Posts,其中包含有关帖子的信息。

          id: {
                type: DataTypes.INTEGER.UNSIGNED,
                autoIncrement: true,
                primaryKey: true,
                allowNull: false,
          },
          content: {
                type: DataTypes.TEXT,
                allowNull: false,
          },
          postedBy: {
                type: DataTypes.INTEGER.UNSIGNED,
                allowNull: false,
          },

我只想获取那些与我有关系的用户(如 friends)的帖子列表,这意味着我的 id 假设是 1 并且它在 userId1 列和 userId2 列中有 id,然后我想从 posts 2 的帖子>postedBy 列。 这种情况反之亦然,因为我的 id 可以在 userId2 列中,我需要获取值在 userId1 列中的用户的所有帖子。

我已经阅读了所有问题和答案,例如多个关联,但它对我不起作用。

这是我在帖子模型中的关联

      Posts.hasOne(RelationModel, {
        foreignKey: 'userId1',
        sourceKey: 'postedBy',
        as: 'first',
      })

       Posts.hasOne(RelationModel, {
            foreignKey: 'userId2',
            sourceKey: 'postedBy',
            as: 'second',
        })

下面是我的包含数组。

          include:[
                   {
                    model: RelationModel,
                    as: 'first',
                    where: {
                        status: 'accepted',
                        [Op.or]: [
                            { userId1: request.user.id },
                            { userId2: request.user.id },
                        ],
                    },
                },
                {
                    model: RelationModel,
                    as: 'second',
                    where: {
                        status: 'accepted',
                        [Op.or]: [
                            { userId1: request.user.id },
                            { userId2: request.user.id },
                        ],
                    },
                }
               ]

由此生成的查询如下,其中 151 是登录的用户 id,表示我的 id

SELECT 
    `posts`.*,
    `first`.*,
    `second`.*
FROM
    `posts` AS `posts`
        INNER JOIN
    `relations` AS `first` ON `posts`.`postedBy` = `first`.`userId1`
        AND (`first`.`userId1` = 151
        OR `first`.`userId2` = 151)
        AND `first`.`status` = 'accepted'
        INNER JOIN
    `relations` AS `second` ON `posts`.`postedBy` = `second`.`userId2`
        AND (`second`.`userId1` = 151
        OR `second`.`userId2` = 151)
        AND `second`.`status` = 'accepted'
WHERE
    `posts`.`deletedAt` IS NULL
ORDER BY `posts`.`id` ASC , `posts`.`id` ASC;

但我要构建的查询在下面

SELECT 
    `posts`.*,
    `first`.*
FROM
    `posts` AS `posts`
        INNER JOIN
    `relations` AS `first` ON (`posts`.`postedBy` = `first`.`userId2`
        OR `posts`.`postedBy` = `first`.`userId1`)
        AND (`first`.`userId1` = 151
        OR `first`.`userId2` = 151)
        AND `first`.`isFriend` = TRUE
        AND `first`.`status` = 'accepted'
WHERE
    `posts`.`deletedAt` IS NULL
ORDER BY `posts`.`id` ASC , `posts`.`id` ASC;

如何在 sequelize 中构造这个查询?

【问题讨论】:

    标签: mysql node.js sequelize.js


    【解决方案1】:

    您需要为关联中的每个关系以及查询的include 指定唯一的as 关键字。

    Posts.hasOne(RelationModel, {
      foreignKey: 'userId1',
      sourceKey: 'postedBy',
      as: 'first',
    });
    
    Posts.hasOne(RelationModel, {
      foreignKey: 'userId2',
      sourceKey: 'postedBy',
      as: 'second',
    });
    

    然后,当您查询时,您指定唯一的 as 来标识连接的关系

    Post.findByPk(id, {
      include: [{
        model: RelationModel,
        as: 'first',
      },
      {
        model: RelationModel,
        as: 'second',
      }],
    });
    

    【讨论】:

    • 感谢您的回复,我已经这样做了,但忘记添加它,我已经更新了我的问题,请看一下。