pilagod / gorm-cursor-paginator

A paginator doing cursor-based pagination based on GORM
https://github.com/pilagod/gorm-cursor-paginator
MIT License
192 stars 44 forks source link

Ability to get a cursor from a specific value after paginate #14

Closed dadgar closed 4 years ago

dadgar commented 4 years ago

Imagine the case where a List API uses pagination but it is paginated over rows in the DB that have to be filtered outside of the DB query because of access control restrictions. Such a list endpoint would look something like this:

  1. Fetch an initial batch of rows for a page without regard to permissions.
  2. Test whether each item is displayable to the current user.
  3. Store the displayable items.
  4. Fetch more items if the quota intended for display on the page (say, 10 items) isn’t met.
  5. Repeat until the quota for the page is filled.

The issue here is that the final DB cursor may be ahead of the last item being returned to the user. Imagine we fetched 10 rows at a time and we filled our page size quota at element 3. It would be nice if there was an API to pass in the object at element 2 and get a cursor value back. This cursor could then be returned to the user.

pilagod commented 4 years ago

Hello @dadgar, thanks for your detailed scenario explanation, it's quite clear.

In fact, there is cursor encode & decode API but I haven't documented it in README. Here is a quick example:

type Model struct {
    ID          int
    CreatedAt   time.Time
}

keys := []string{"ID", "CreatedAt"} // same as those keys (including order) for paginating

// cursor encoder
encoder := paginator.NewCursorEncoder(keys...)
cursor := encoder.Encode(Model{})

// cursor decoder
cursor := "some cursor"
decoder, _ := paginator.NewCursorDecoder(Model{}, keys...)
fields := decoder.Decode(cursor)

Do you think current API meet your need? If it is not enough, please let me know any thought to make it better.

If it is OK, I will soon document this API to README, thanks 😃

dadgar commented 4 years ago

@pilagod Thanks for the kind response! I totally missed that API. I think what you outlined here would be a good addition to the README. Thank you!