38

有什么方法可以通过单个查询获取总计数和记录,而不是将其作为 2 个单独的查询运行?

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

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

  const builder = this.userRepository.createQueryBuilder("user")
  const total = await builder.where("user.name like :name", { name: '%' + keyword + '%' }).getCount()
  const data = await builder.where("user.name like :name", { name: '%' + keyword + '%' }).orderBy('name', 'DESC').skip(skip).take(take).getMany();

  return {
    data: data,
    count: total
  }
}

{
  count: 10,
  data: [
    {
      id: 1,
      name: 'David'
    },
    {
      id: 2,
      name: 'Alex'
    }]
}
4

5 回答 5

101

你可以在这个项目中找到一些很好的例子。简而言之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
    }
}

您可以在此处找到存储库 API 。更多关于Repository类的文档可以在这里找到。

于 2018-12-25T13:12:54.510 回答
11

加起来...

这个中间件检查你是否在 URL 中有 take 和 skip 参数,如果有,它会从字符串转换为数字,如果你不使用默认值。10 为拍摄,0 为跳过。

take 是每页和跳过的结果数,它应该从哪里开始读取记录。

有了这个,我设置为 GET 方法拦截“产品/分页”路由。

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

文件夹

@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 };
  }
}

好的?

于 2019-11-01T13:03:29.843 回答
7

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

  • 端点示例:/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
        }
    }
    

    2/。更好的方法(处理响应):

     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,
      }
    }
    
于 2021-04-24T04:08:37.407 回答
3

您还可以查看 NestJS 和 TypeORM 的这个包:

https://github.com/nestjsx/nestjs-typeorm-paginate

于 2020-07-04T12:45:00.820 回答
-1

如果您需要对许多记录进行分页,即多次迭代(可能在迁移或大规模更新期间)。

async getPaginatedResults(query: any, transactionManager?: EntityManager): Promise<any> {

}
于 2019-04-29T19:32:59.537 回答