You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeORM/NestJS的findAll方法中实现分页功能?

TypeORM 分页功能实现方案

问题根源

你之前的代码混用了TypeORM的两种查询模式:

  • createQueryBuilder 链式查询模式
  • findAndCount 选项式查询模式
    findAndCount的where参数要求传入查询条件对象,你传入query.getMany()的返回值(Promise数组)完全不符合参数要求,因此触发报错。

最优修改方案(复用现有QueryBuilder逻辑,改动最小)

你已经写好了动态where条件的QueryBuilder代码,不需要切换到findAndCount,直接在现有QueryBuilder基础上追加分页参数即可,修改后的完整findAll代码如下:

async findAll(queryCertificateDto: QueryCertificateDto, page = 1): Promise<PaginatedResult> {
    const { country, sponser } = queryCertificateDto;
    // 单页条数固定为10,可根据需求调整为参数传入
    const pageSize = 10;
    const skip = (page - 1) * pageSize;

    const query = this.certificateRepository.createQueryBuilder('certificate');

    if (sponser) {
        const upperSponser = sponser.toUpperCase();
        query.andWhere('UPPER(certificate.sponser) = :sponser', { sponser: upperSponser });
    }

    if (country) {
        const upperCountry = country.toUpperCase();
        query.andWhere('UPPER(certificate.country) = :country', { country: upperCountry });
    }

    // 追加分页参数,调用getManyAndCount直接获取[数据集, 总条数]
    const [certificates, total] = await query
        .skip(skip)
        .take(pageSize)
        .getManyAndCount();

    // 组装符合PaginatedResult格式的返回值
    return {
        data: certificates,
        meta: {
            total,
            page,
            last_page: Math.ceil(total / pageSize)
        }
    };
}

代码说明

  • skip 计算规则:当前页码减1乘以单页条数,实现跳过前N页已查询的数据
  • take 对应单页返回条数,这里固定为10符合你的需求,也可以改成参数动态传入
  • getManyAndCount 是QueryBuilder提供的原生分页方法,一次查询同时返回符合条件的数据集和总记录数,不需要单独调用两次查询
  • 最后返回的结构完全匹配你定义的PaginatedResult类要求,无需额外处理

可选方案:纯findAndCount实现

如果你想改用findAndCount的写法,也可以参考如下代码,无需使用QueryBuilder:

async findAll(queryCertificateDto: QueryCertificateDto, page = 1): Promise<PaginatedResult> {
    const { country, sponser } = queryCertificateDto;
    const pageSize = 10;
    const skip = (page - 1) * pageSize;
    const whereConditions = {};

    if (sponser) {
        // 注意:如果用findAndCount做大写匹配,需要开启数据库的大小写不敏感,或者用ILike(PostgreSQL)/ Like配合UPPER函数
        whereConditions['sponser'] = sponser.toUpperCase();
    }
    if (country) {
        whereConditions['country'] = country.toUpperCase();
    }

    const [certificates, total] = await this.certificateRepository.findAndCount({
        where: whereConditions,
        skip,
        take: pageSize
    });

    return {
        data: certificates,
        meta: {
            total,
            page,
            last_page: Math.ceil(total / pageSize)
        }
    };
}

注意:如果数据库字段是大小写敏感的,findAndCount写法需要额外调整匹配逻辑,更推荐第一种复用QueryBuilder的方案

内容的提问来源于stack exchange,提问作者Shruti sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 11:45:08