Is there any way to get the total count and records with a single query, instead of running it as 2 separate queries?
If it's not possible, is there any way to reuse the where condition in both queries?
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' }] }
ORMs in NestJS Object-relational mapping (ORM) is a technique that abstracts your database tables to data objects in memory. It allows you to query and write data to databases using data objects. ORMs are used to make database access easier, as developers won't need to write raw queries.
Pagination is the process of separating print or digital content into discrete pages. For print documents and some online content, pagination also refers to the automated process of adding consecutive numbers to identify the sequential order of pages.
You can find some nice example in this project. In short typeorm
has a really nice method specific to this usecase 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 } }
Repository API you can find here. More documentation about Repository
class can be found here.
summing up...
This middleware checks if you have the take and skip parameters in the URL, if it does, it converts from string to number, if you don't use the default values. 10 for take and 0 for skip.
take is the number of results per page and skip, from where it should start reading records.
With that, I set up to intercept the "product / paged" route just for the GET method.
With this I can retrieve these values in the controller and pass to TypeORM or an SQL query.
@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 }; } }
ok?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With