在多对多关系中计数 Sequelize
Counting in Many-To-Many Relations Sequelize
我正在尝试计算用户的关注者和关注者数量。
作为 followingCount
和 followerCount
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
是具有列 followeeId
和 followerId
的联合 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 个分区以准确计算 followers
或 followees
。
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: [],
}
},
],
});
我正在尝试计算用户的关注者和关注者数量。
作为 followingCount
和 followerCount
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
是具有列 followeeId
和 followerId
的联合 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 个分区以准确计算 followers
或 followees
。
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: [],
}
},
],
});