【问题标题】:Sequelize - Pagination works not correct in findAndCountAll when relations count functions addedSequelize - 添加关系计数函数时,findAndCountAll 中的分页工作不正确
【发布时间】:2022-08-19 06:46:01
【问题描述】:

我正在尝试使用 findAndCountAll 方法实现分页,但是在我为关系表添加计数函数后,它给了我一个包含许多重复行的结果,例如,我有两个作者的 Authors 表,以及只有两行的 AuthorFollowers 表的 m2m 关系,所以它应该只给我两个作者行 count: 2followersCount: 2,但它给了我 9 个作者行。如果我使用distinct: true,它显示正确的行和count: 2,但实际上当我使用限制和偏移字段时,它的行为就像有9行,所以如果我设置limit: 1应该只有2页,但有 9 页。如果我不使用distinct: true,我的查询结果将不正确:{ count: 9, rows:...}

我的方法:

async findAll(paginate: PaginateDto) {
    const followerIdCol = \'\"author_followers->AuthorsFollowers\".\"followerId\"\'
    const authorTokensCol = \'\"author_tokens\".\"id\"\'
    return await this.authorRepository.findAndCountAll({
        attributes: {
            exclude: [\'collections\', \'updatedAt\', \'userId\'],
            include: [
                [
                    literal(`COUNT(${authorTokensCol}) OVER (PARTITION BY \"Author\".\"id\", ${followerIdCol})`),
                    \'tokensCount\',
                ],
                [
                    literal(`COUNT(${followerIdCol}) OVER (PARTITION BY \"Author\".\"id\", ${authorTokensCol})`),
                    \'followersCount\',
                ],
            ],
        },
        include: [
            { model: Token, as: \'author_tokens\', attributes: [], duplicating: false },
            {
                model: User,
                as: \'author_followers\',
                attributes: [],
                through: { attributes: [] },
                duplicating: false,
            },
        ],
        offset: !paginate || !paginate.limit || !paginate.page ? null : 0 + (+paginate.page - 1) * +paginate.limit,
        limit: !paginate || !paginate.limit ? null : paginate.limit,
        order: [[\'createdAt\', \'ASC\']],
        distinct: true,
    })
}

如果我没有应用限制和偏移,此方法会给出正确的结果:

{
  \"count\": 2,
  \"rows\": [
    {
      \"id\": \"67585770-4728-44c7-8a02-ce9efc5273a5\",
      \"createdAt\": \"2022-08-03T19:41:41.856Z\",
      \"tokensCount\": \"4\",
      \"followersCount\": \"2\"
    },
    {
      \"id\": \"eeb84240-9cd7-4268-97c0-b6c92fd5a45e\",
      \"createdAt\": \"2022-08-03T19:45:09.015Z\",
      \"tokensCount\": \"0\",
      \"followersCount\": \"1\"
    }
  ]
}

如果我尝试设置限制和偏移量,它的工作方式就像有 9 行而不是 2 行一样,因为实际上我的方法会生成错误的查询,结果是 9 行而不是 2 行:

SELECT 
  \"Author\".\"id\", 
  \"Author\".\"createdAt\", 
  COUNT(\"author_tokens\".\"id\") OVER (
    PARTITION BY \"Author\".\"id\", \"author_followers->AuthorsFollowers\".\"followerId\"
  ) AS \"tokensCount\", 
  COUNT(
    \"author_followers->AuthorsFollowers\".\"followerId\"
  ) OVER (
    PARTITION BY \"Author\".\"id\", \"author_tokens\".\"id\"
  ) AS \"followersCount\" 
FROM 
  \"authors\" AS \"Author\" 
  LEFT OUTER JOIN \"tokens\" AS \"author_tokens\" ON \"Author\".\"id\" = \"author_tokens\".\"authorId\" 
  LEFT OUTER JOIN (
    \"authors_folowers\" AS \"author_followers->AuthorsFollowers\" 
    INNER JOIN \"users\" AS \"author_followers\" ON \"author_followers\".\"id\" = \"author_followers->AuthorsFollowers\".\"followerId\"
  ) ON \"Author\".\"id\" = \"author_followers->AuthorsFollowers\".\"followingId\" 
ORDER BY 
  \"Author\".\"createdAt\" ASC;

\"67585770-4728-44c7-8a02-ce9efc5273a5\"  \"2022-08-03 12:41:41.856-07\"    4   2
\"67585770-4728-44c7-8a02-ce9efc5273a5\"  \"2022-08-03 12:41:41.856-07\"    4   2
\"67585770-4728-44c7-8a02-ce9efc5273a5\"  \"2022-08-03 12:41:41.856-07\"    4   2
\"67585770-4728-44c7-8a02-ce9efc5273a5\"  \"2022-08-03 12:41:41.856-07\"    4   2
\"67585770-4728-44c7-8a02-ce9efc5273a5\"  \"2022-08-03 12:41:41.856-07\"    4   2
\"67585770-4728-44c7-8a02-ce9efc5273a5\"  \"2022-08-03 12:41:41.856-07\"    4   2
\"67585770-4728-44c7-8a02-ce9efc5273a5\"  \"2022-08-03 12:41:41.856-07\"    4   2
\"67585770-4728-44c7-8a02-ce9efc5273a5\"  \"2022-08-03 12:41:41.856-07\"    4   2
\"eeb84240-9cd7-4268-97c0-b6c92fd5a45e\"  \"2022-08-03 12:45:09.015-07\"    0   1

但是这个在 SELECT 之后使用 DISTINCT 关键字的查询可以正常工作,即使我添加了限制和偏移值:

SELECT DISTINCT
  \"Author\".\"id\", 
  \"Author\".\"createdAt\", 
  COUNT(\"author_tokens\".\"id\") OVER (
    PARTITION BY \"Author\".\"id\", \"author_followers->AuthorsFollowers\".\"followerId\"
  ) AS \"tokensCount\", 
  COUNT(
    \"author_followers->AuthorsFollowers\".\"followerId\"
  ) OVER (
    PARTITION BY \"Author\".\"id\", \"author_tokens\".\"id\"
  ) AS \"followersCount\" 
FROM 
  \"authors\" AS \"Author\" 
  LEFT OUTER JOIN \"tokens\" AS \"author_tokens\" ON \"Author\".\"id\" = \"author_tokens\".\"authorId\" 
  LEFT OUTER JOIN (
    \"authors_folowers\" AS \"author_followers->AuthorsFollowers\" 
    INNER JOIN \"users\" AS \"author_followers\" ON \"author_followers\".\"id\" = \"author_followers->AuthorsFollowers\".\"followerId\"
  ) ON \"Author\".\"id\" = \"author_followers->AuthorsFollowers\".\"followingId\" 
ORDER BY 
  \"Author\".\"createdAt\" ASC;

\"67585770-4728-44c7-8a02-ce9efc5273a5\"  \"2022-08-03 12:41:41.856-07\"    4   2
\"eeb84240-9cd7-4268-97c0-b6c92fd5a45e\"  \"2022-08-03 12:45:09.015-07\"    0   1

如何修复我的 sequelize 方法以在 SELECT 之后添加 DISTINCT 关键字?或者可能=有另一种方法来解决这个问题?

谢谢!

    标签: postgresql sequelize.js nestjs


    【解决方案1】:

    回答我自己的问题。经过多次尝试,我找到了避免 N+1 问题的解决方案。此解决方案是使用带有直接原始查询的文字,而不是使用包含的查询:

    async findAll2(paginate?: FilndAllAuthorsFiltersDto) {
        return await this.authorRepository.findAndCountAll({
            attributes: [
                'id',
                'userId',
                'createdAt',
                [literal('(SELECT COUNT(*) from tokens where "authorId"="Author"."id")'), 'tokensCount'],
                [
                    literal('(SELECT COUNT(*) from authors_folowers where "followingId"="Author"."id")'),
                    'followersCount',
                ],
            ],
            offset: !paginate || !paginate.limit || !paginate.page ? null : 0 + (+paginate.page - 1) * +paginate.limit,
            limit: !paginate || !paginate.limit ? null : paginate.limit,
            order: [
                [
                    paginate.sortBy === 'byFollowersCount' ? literal('"followersCount"') : 'createdAt',
                    paginate.sortDirection,
                ],
            ],
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-27
      • 1970-01-01
      • 2017-10-31
      • 1970-01-01
      • 2023-01-26
      • 2021-05-21
      • 2021-12-02
      • 1970-01-01
      • 2014-08-06
      相关资源
      最近更新 更多