Nest.js | Prisma Pagination
NestJS is a framework for building efficient, scalable Node.js server-side applications. Prisma is a powerful ORM (Object-Relational Mapping) tool that can be used with NestJS to interact with databases. To enable pagination in a NestJS application using Prisma, you can use the skip
and take
options in the prisma.query
or prisma.mutation
methods to limit the number of records returned in a query. For example, to retrieve the second page of a list of users with a page size of 10, you can use the following query:
const users = await prisma.query.users({
skip: 10,
take: 10
});
Here’s an example of a simple pagination function that can be used to paginate a list of data using NestJS and Prisma:
import PrismaService from '@providers/prisma/prisma.service';
import { PaginatedResult, PaginateFunction, paginator } from '@providers/prisma/paginator';
import { User, Prisma } from '@prisma/client';
const paginate: PaginateFunction = paginator({ perPage: 10 });
@Injectable()
export default class UserRepository {
constructor(private prisma: PrismaService) {}
async findMany({ where, orderBy, page }:{
where?: Prisma.UserWhereInput,
orderBy?: Prisma.UserOrderByWithRelationInput,
page?: number,
}): Promise<PaginatedResult<User>> {
return paginate(
this.prisma.user,
{
where,
orderBy,
},
{
page,
},
);
}
}
Let's see implementation of this paginator in paginator.ts:
export interface PaginatedResult<T> {
data: T[]
meta: {
total: number
lastPage: number
currentPage: number
perPage: number
prev: number | null
next: number | null
}
}
export type PaginateOptions = { page?: number | string, perPage?: number | string }
export type PaginateFunction = <T, K>(model: any, args?: K, options?: PaginateOptions) => Promise<PaginatedResult<T>>
export const paginator = (defaultOptions: PaginateOptions): PaginateFunction => {
return async (model, args: any = { where: undefined }, options) => {
const page = Number(options?.page || defaultOptions?.page) || 1;
const perPage = Number(options?.perPage || defaultOptions?.perPage) || 10;
const skip = page > 0 ? perPage * (page - 1) : 0;
const [total, data] = await Promise.all([
model.count({ where: args.where }),
model.findMany({
...args,
take: perPage,
skip,
}),
]);
const lastPage = Math.ceil(total / perPage);
return {
data,
meta: {
total,
lastPage,
currentPage: page,
perPage,
prev: page > 1 ? page - 1 : null,
next: page < lastPage ? page + 1 : null,
},
};
};
};
Example of result:
{
"data": [
{
"id": 1,
"firstName": null,
"lastName": null,
"dateOfBirth": null,
"email": "test@gmail.com",
"zipCode": null,
"city": null,
"avatar": null
},
...
],
"meta": {
"total": 5,
"lastPage": 1,
"currentPage": 1,
"perPage": 10,
"prev": null,
"next": null
}
}
If you have any questions or feedback about this article, feel free to leave a comment.