Typescript 如何用typeorm在nestjs中实现分页

Typescript 如何用typeorm在nestjs中实现分页,typescript,nestjs,typeorm,Typescript,Nestjs,Typeorm,是否有任何方法可以通过单个查询获得总计数和记录,而不是将其作为两个单独的查询运行 如果不可能,有没有办法在两个查询中重用where条件 异步findAll(查询):Promise{ const take=query.take | | 10 const skip=query.skip | 0 const keyword=query.keyword | |“” const builder=this.userRepository.createQueryBuilder(“用户”) const total

是否有任何方法可以通过单个查询获得总计数和记录,而不是将其作为两个单独的查询运行

如果不可能,有没有办法在两个查询中重用where条件

异步findAll(查询):Promise{ const take=query.take | | 10 const skip=query.skip | 0 const keyword=query.keyword | |“” const builder=this.userRepository.createQueryBuilder(“用户”) const total=await builder.where(“user.name like:name”,{name:'%2!'+关键字+'%})。getCount() const data=await builder.where(“user.name like:name”,{name:'%2!'+关键字+'%}).orderBy('name','DESC').skip(skip).take(take).getMany(); 返回{ 数据:数据, 计数:总数 } } { 计数:10, 数据:[ { id:1, 姓名:“大卫” }, { id:2, 姓名:“亚历克斯” }] }
你可以在这里找到一些很好的例子。简而言之,
typeorm
有一个非常好的方法专门用于这个用例
findAndCount

async findAll(query): Promise<Paginate> {
    const take = query.take || 10
    const skip = query.skip || 0
    const keyword = query.keyword || ''

    const [result, total] = await this.userRepository.findAndCount(
        {
            where: { name: Like('%' + keyword + '%') }, order: { name: "DESC" },
            take: take,
            skip: skip
        }
    );

    return {
        data: result,
        count: total
    }
}
异步findAll(查询):Promise{ const take=query.take | | 10 const skip=query.skip | 0 const keyword=query.keyword | |“” const[result,total]=等待this.userRepository.findAndCount( { 其中:{name:Like('%'+关键字+'%')},顺序:{name:“DESC”}, 拿,拿, 跳过:跳过 } ); 返回{ 数据:结果, 计数:总数 } }
您可以找到的存储库API。可以找到有关
存储库
类的更多文档

如果您需要对许多记录进行分页,例如多次迭代(可能在迁移或批量更新期间)

async getPaginatedResults(查询:any,transactionManager?:EntityManager):承诺{
}
总结


这个中间件检查URL中是否有take和skip参数,如果有,它将从字符串转换为数字,如果不使用默认值。10表示take,0表示skip

take是每页和跳过的结果数,从这里开始读取记录

有了它,我设置了拦截“product/paged”路由,只是为了GET方法

有了它,我可以在控制器中检索这些值并传递给TypeORM或SQL查询

并在模块中应用。 控制器 和服务
@Injectable()
出口类服务{
建造师(
@注入存储库(YourEntity)
私人只读回购:MongoRepository
) {}
异步findAll(take:number=10,skip:number=0){
const[data,total]=等待this.repo.findAndCount({take,skip});
返回{data,total};
}
}

好吗?

您还可以查看这个用于NestJS和TypeORM的软件包:


我更喜欢使用页面,而不是直接跳过

  • 端点示例:
    /users?page=4&take=3

    async findAll(query): Promise<Paginate> {
        const take = query.take || 10
        const page=query.page || 1;
        const skip= (page-1) * take ;
        const keyword = query.keyword || ''
    
        const [result, total] = await this.userRepository.findAndCount(
            {
                where: { name: Like('%' + keyword + '%') }, order: { name: "DESC" },
                take: take,
                skip: skip
            }
        );
    
        return {
            data: result,
            count: total
        }
    }
    
    异步findAll(查询):Promise{ const take=query.take | | 10 const page=query.page | | 1; 常量跳过=(第1页)*取; const keyword=query.keyword | |“” const[result,total]=等待this.userRepository.findAndCount( { 其中:{name:Like('%'+关键字+'%')},顺序:{name:“DESC”}, 拿,拿, 跳过:跳过 } ); 返回{ 数据:结果, 计数:总数 } }
2/。更好的方法(处理响应):

异步findAll(查询):Promise{ const take=query.take | | 10 const page=query.page | | 1; 常量跳过=(第1页)*取; const keyword=query.keyword | |“” const data=wait this.userRepository.findAndCount( { 其中:{name:Like('%'+关键字+'%')},顺序:{name:“DESC”}, 拿,拿, 跳过:跳过 } ); 返回分页响应(数据、页面、限制) }
导出函数分页响应(数据、页面、限制){
常量[结果,总计]=数据;
const lastPage=Math.ceil(总计/限额);
const nextPage=page+1>lastPage?空:page+1;
const prevPage=page-1<1?空:page-1;
返回{
状态代码:“成功”,
数据:[……结果],
总数:,
当前页:第页,
下一页:下一页,
prevPage:prevPage,
最后一页:最后一页,
}
}

非常感谢您,两个URL对于像我这样刚开始学习打字脚本的新手来说非常有用^^欢迎!如果您也能对答案进行投票,我将不胜感激。这是一个很好的示例,但请注意,Like(“%”+关键字+“%”)将只在SQL数据库上有效,而不会在mongodb上有效。我找不到findAndCount在我的模型上。。。仅FindI如果要使用ClassSerializerInterceptor,我对其进行了一些更改,使其接受类型为
[Array,number]
的返回值。在这方面有点有用。因此,您只需返回
getManyAndCount()
,数据就会被序列化。检查:请描述您的答案此中间件检查URL中是否有take和skip参数,如果有,它将从字符串转换为数字,如果您不使用默认值。10表示take,0表示skip。take是每页和跳过的结果数,从这里开始读取记录。有了它,我设置了拦截“product/paged”路由,只是为了GET方法。有了它,我可以在控制器中检索这些值,并将其传递给TypeORM或SQL查询。您可能不需要中间件,只需执行标准的DTO,它就更干净了。
@Injectable()
export class PagerMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    req.query.take = +req.query.take || 10;
    req.query.skip = +req.query.skip || 0;
    next();
  }
}
export class AdminFeatureApi implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(PagerMiddleware)
    .forRoutes({ path: 'product/paged', method: RequestMethod.GET })
  }
}
@Controller('product')
export class TrainingDomainController {
  constructor(private service: YourService) {}

  @Get('paged')
  get(@Query() { take, skip }) {
    return this.service.findAll(take, skip);
  }
}
@Injectable()
export class YourService {
  constructor(
    @InjectRepository(YourEntity)
    private readonly repo: MongoRepository<YourEntity>
  ) {}

  async findAll(take: number = 10, skip: number = 0) {
    const [data, total] = await this.repo.findAndCount({ take, skip });
    return { data, total };
  }
}
async findAll(query): Promise<Paginate> {
    const take = query.take || 10
    const page=query.page || 1;
    const skip= (page-1) * take ;
    const keyword = query.keyword || ''

    const [result, total] = await this.userRepository.findAndCount(
        {
            where: { name: Like('%' + keyword + '%') }, order: { name: "DESC" },
            take: take,
            skip: skip
        }
    );

    return {
        data: result,
        count: total
    }
}
 async findAll(query): Promise<Paginate> {
     const take = query.take || 10
     const page=query.page || 1;
     const skip= (page-1) * take ;
     const keyword = query.keyword || ''

     const data = await this.userRepository.findAndCount(
         {
             where: { name: Like('%' + keyword + '%') }, order: { name: "DESC" },
             take: take,
             skip: skip
         }
     );
     return paginateResponse(data ,page,limit)

 }
export function paginateResponse(data,page,limit) {
  const [result, total]=data;
  const lastPage=Math.ceil(total/limit);
  const nextPage=page+1 >lastPage ? null :page+1;
  const prevPage=page-1 < 1 ? null :page-1;
  return {
    statusCode: 'success',
    data: [...result],
    count: total,
    currentPage: page,
    nextPage: nextPage,
    prevPage: prevPage,
    lastPage: lastPage,
  }
}