-
Notifications
You must be signed in to change notification settings - Fork 9
Open
Description
Cursor based pagination
I've separated cursor based pagination from #3 into it's own issue (this one) to keep the discussion about bother feature sets a bit more docused. My notes from my investigation into cursor based pagination are below
Already Mentioned Points
- Cursor based pagination should be pretty easy to implement. However, we would have to think about where to specify the cursor field name (e.g. "id") - is it something that is specified when creating a DirectFilterPipe (only one cursor type allowed) or something that the client hast to send as well? That's especially important, because you always have to sort by the cursor field (otherwise the results are unpredictable)
Notes
- I think that we should specify cursor name at time of building query (something that the client specifies). Once a findMany() endpoint is configured this will mean less rework for future frontend data request requirements.
- We can either include all the required cursor information in a single encoded string or include just the cursor field + value of the next record with the other information mandatorily included in separate query params already established such as orderBy, skip, and limit.
- If a cursor can be expressed in a single query parameter string then this shouldn't be too hard for clients to deal with especially if the next and previous cursor are returned from the nestjs api in each response.
- The cursor field and orderBy field must always be the same
- If no cursor string is provided, the pagination is initialised form the start or end using the provided sort and take information. A next cursor will be generated and return in the metadata to be considered in the next request.
- If a cursor (field + value) is provided, the string will be added to the query.
- Cursor fields must be within the
Prisma.<PrismaModel>WhereUniqueInputType. My previous point in Select fields and pagination aliases #3 about usingPrisma.<PrismaModel>FindManyArgsto initialise the pipe may be useful to be able to extract the Type for the valid cursor field keys and value types. Using thePrisma.<PrismaModel>FindManyArgsType may give us more information to play with while still only needing to use a single type to initialise the pipe.
Proposed Process
- create query parameter
?cursor=...using filter. Builder which includes the following information- no cursor field or value,
- order by,
- take
- skip
- Send request with query parameter
- Extract cursor object into
findOptionsfrom request query parameter using Pipe- no cursor field or value,
- order by,
- take
- skip
- Get record from prisma.finMany() using
findOptionsobject - Generate next and previous cursors to be included in response metadata using the prisma.findMany() data and previous cursor
- use order by, take, and skip from just used query
- calculate cursor field and value using first and last records in retrieved data
- Send response from api to client with requested data and matadata including generated next and previous cursors
- create query parameter
?cursor=...using querybuilder or using generated next cursor send by api in response metadata notes in step 5 & 6- cursor field + value,
- order by,
- take
- skip
Required Information to perform Prisma.findMany() with a cursor
- take value + direction (
number, Integer) - skip value + direction (
number, Integer) - order by (
ISingleOrder<TDto>)- field: (
keyof T & string) - dir: (
FilterOrder)
- field: (
- cursor (
Prisma.<PrismaModel>WhereUniqueInput | undefined)- field (
keyof T & string| undefined) - value (
string | number | string[] | number[] | boolean | null | undefined)
- field (
All of this information will need to be able to be held and expressed in the following ways:
- A query parameter called cursor with type string. e.g.
?cursor=<encodedCursorStringValue> - A set of fields within
findOptionsthat can be set to store cursor information parsed from the query param string. This will then be passed into prisma.findmany() as it already does.
Proposed Functions (To be further explored)
Metadata
Metadata
Assignees
Labels
No labels