Generic prisma pagination #1206
-
Hi folks! We extend our prisma client with a pagination method that's applied to all models:
We have
This generally works for us, but we have what feels like an unnecessary prisma call to re-retrieve the models by ids (and an unnecessary re-sort), as seen in the I am wondering if anyone has any recommendations for how to remove this second prisma call, while also retaining nested resolvers. For example, if Alternatively, we may be approaching pagination wrong, and there may be an easier approach. Thanks for any help! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Just checking in to see if anyone has any thoughts on this, or has any recommendations on generic offset-based pagination with Pothos and Prisma 🙏 |
Beta Was this translation helpful? Give feedback.
-
You can definitely avoid the extra queries. There are a few different options here, but I think the easiest would be to use the import assert from 'node:assert';
import { User as UserModel } from '@prisma/client';
import { queryFromInfo } from '@pothos/plugin-prisma';
builder.simpleObject('PaginatedUser', {
description: 'Paginated version of the User type',
fields: t => ({
take: t.int(),
skip: t.int(),
count: t.int(),
data: t.field({
type: User,
}),
}),
});
type ResolveUserArgs = {
query: {}, // { select?: UserSelect, include?: UserInclude }
context: GraphQLContext;
input: {
skip: number;
take: number;
};
};
const resolveUser = async ({ query, input, context }: ResolveUserArgs) => {
return context.prisma.user.paginate({
// assumes that your paginate can take arbitrary select/include options
...query,
skip: input.skip,
take: input.take,
});
};
builder.queryField('user', t =>
t.fieldWithInput({
input: {
take: t.input.int({ required: true }),
skip: t.input.int({ required: true }),
},
type: PaginatedUser,
resolve: async (_root, args, context: GraphQLContext, info) => {
return resolveUser({
query: queryFromInfo({
path: ['data'],
info,
context,
}),
input: args.input,
context
});
},
}),
);
export const User = builder.prismaObject('User', {
fields: t => ({
id: t.exposeID('id'),
email: t.exposeString('email', { nullable: true }),
firstName: t.exposeString('firstName', { nullable: true }),
lastName: t.exposeString('lastName', { nullable: true }),
numberOfFriends: t.relationCount('friends'),
}),
}); I didn't test this, but this general pattern should work pretty well to eliminate extra requests |
Beta Was this translation helpful? Give feedback.
You can definitely avoid the extra queries. There are a few different options here, but I think the easiest would be to use the
queryFromInfo
helper to directly load nested selections, and maybe add in thesimpleObjects
plugin for the extra pagination types