在多对多关系中计数 Sequelize

Counting in Many-To-Many Relations Sequelize

我正在尝试计算用户的关注者和关注者数量。 作为 followingCountfollowerCount

User Model

User.init(
    {
      id: {
        allowNull: false,
        primaryKey: true,
        type: DataTypes.UUID,
        defaultValue: DataTypes.UUIDV4,
      },
      email: {
        type: DataTypes.STRING,
      },
      password: {
        type: DataTypes.STRING,
      },
    }
  );

static associate(models) {
      // Follow relationship
      this.belongsToMany(models.User, {
        through: 'UserFollow',
        foreignKey: 'followerId',
        as: 'following',
      });

      // Follow relationship
      this.belongsToMany(models.User, {
        through: 'UserFollow',
        foreignKey: 'followeeId',
        as: 'follower',
      });
    }

其中 UserFollow 是具有列 followeeIdfollowerId 的联合 Table。

我目前查找追随者数量的方法是这样的:


const user = await User.findOne({
      where: {
        id,
      },
      attributes: [
        'id',
        'userName',
        'email',
        [sequelize.fn('COUNT', sequelize.col('following->UserFollow.followeeId')), 'followingCount'],
      ],
      include: [
        {
          model: User,
          as: 'following',
          attributes: ['id', 'userName', 'email'],
          through: {
            attributes: [],
          },
        },
      ],
      group: ['User.id', 'following.id'],
    });

    return user;

得到的输出是这样的:

这里我得到 followingCount 作为 1... 但它应该是 3.

"data": {
        "id": "1af4b9ea-7c58-486f-a37a-e46461487b06",
        "userName": "xyz",
        "email": "xyz@gmail.com",
        "followingCount": "1",         <------ I want this to be 3
        "following": [
            {
                "id": "484202b0-a6d9-416d-a8e2-6681deffa3d1",
                "userName": "uqwheuo",
                "email": "uqwheuo@gmail.com"
            },
            {
                "id": "56c8d9b0-f5c6-4b2e-b32c-be6363294614",
                "userName": "aiwhroanc",
                "email": "aiwhroanc@gmail.com"
            },
            {
                "id": "9a3e4074-c7a0-414e-8df4-cf448fbaf5fe",
                "userName": "iehaocja",
                "email": "iehaocja@gmail.com"
            }
        ]
    }

我无法在关节中计数 Table..

您得到 followingCount: 1 的原因是您按 following.id (followeeId) 分组。它只计算唯一的 followeeId,它总是 1.

不过,如果您从 group 中取出 following.id,SQL 将不再起作用。它会因“列必须出现在 GROUP BY 子句中...”而崩溃。这是 Postgres 中的一个常见问题,此 link () 详细解释了该主题。

要解决您的问题,您可以使用 COUNT OVER (PARTITION BY).

而不是 group
const user = await User.findOne({
  where: {
    id,
  },
  attributes: [
    'id',
    'userName',
    'email',
    [Sequelize.literal('COUNT("following->UserFollow"."followeeId") OVER (PARTITION BY "User"."id")'), 'followingCount']
  ],
  include: [
    {
      model: User,
      as: 'following',
      attributes: ['id', 'userName', 'email'],
      through: {
        attributes: [],
      }
    },
  ],
});

============================================= =========

更新:

原查询只抓取“following”关系。为了获取该用户的关注者,您首先需要添加“关注者”关联。

然后,由于添加了 2 个关联,我们需要按列再添加 1 个分区以准确计算 followersfollowees

const followeeIdCol = '"following->UserFollow"."followeeId"';
const followerIdCol = '"follower->UserFollow"."followerId"';

const user = await User.findOne({
  where: {
    id,
  },
  attributes: [
    'id',
    'userName',
    'email',
    // Note that the COUNT column and partition by column is reversed.
    [Sequelize.literal(`COUNT(${followeeIdCol}) OVER (PARTITION BY "Users"."id", ${followerIdCol})`), 'followingCount'],
    [Sequelize.literal(`COUNT(${followerIdCol}) OVER (PARTITION BY "Users"."id", ${followeeIdCol})`), 'followerCount'],
  ],
  include: [
    {
      model: User,
      as: 'following',
      attributes: ['id', 'userName', 'email'],
      through: {
        attributes: [],
      }
    },
    {
      model: User,
      as: 'follower',       // Add follower association
      attributes: ['id', 'userName', 'email'],
      through: {
        attributes: [],
      }
    },
  ],
});