All Projects → pilagod → gorm-cursor-paginator

pilagod / gorm-cursor-paginator

Licence: MIT License
A paginator doing cursor-based pagination based on GORM

Programming Languages

go
31211 projects - #10 most used programming language
Makefile
30231 projects

Projects that are alternatives of or similar to gorm-cursor-paginator

gorm-paginator
gorm pagination extension
Stars: ✭ 154 (+67.39%)
Mutual labels:  pagination, gorm
MR.EntityFrameworkCore.KeysetPagination
Keyset/Seek/Cursor pagination for Entity Framework Core.
Stars: ✭ 19 (-79.35%)
Mutual labels:  pagination, cursor-pagination
go-paginate
Cursor-based go paginator
Stars: ✭ 48 (-47.83%)
Mutual labels:  pagination, gorm
Gorm Paginator
gorm pagination extension
Stars: ✭ 136 (+47.83%)
Mutual labels:  pagination, gorm
rails cursor pagination
Add cursor pagination to your ActiveRecord backed application
Stars: ✭ 21 (-77.17%)
Mutual labels:  pagination, cursor-pagination
TableBundle
Symfony Bundle for easy pagination and filtering
Stars: ✭ 24 (-73.91%)
Mutual labels:  pagination
Pageable
An easy way to Pagination or Infinite scrolling for TableView/CollectionView
Stars: ✭ 44 (-52.17%)
Mutual labels:  pagination
Go-bjut
A bbs system.
Stars: ✭ 60 (-34.78%)
Mutual labels:  gorm
f3-pagination
A pagebrowser and some pagination utilities for the PHP Fat-Free Framework
Stars: ✭ 15 (-83.7%)
Mutual labels:  pagination
uni-z-paging
【uni-app自动分页器】超简单!仅需两步轻松完成完整分页逻辑(下拉刷新、上拉加载更多),分页全自动处理。支持自定义加载更多的文字或整个view,自定义下拉刷新样式,自动管理空数据view等。
Stars: ✭ 91 (-1.09%)
Mutual labels:  pagination
pagination
No description or website provided.
Stars: ✭ 14 (-84.78%)
Mutual labels:  pagination
Go-Gin-Api
基于golang开源框架 gin封装的api框架
Stars: ✭ 42 (-54.35%)
Mutual labels:  gorm
easy-css-layout
Easy css layout
Stars: ✭ 117 (+27.17%)
Mutual labels:  pagination
echo-gorm-realworld-app
realworld application built with Golang + Echo + Gorm
Stars: ✭ 18 (-80.43%)
Mutual labels:  gorm
go-cms
基于beego框架的cms系统
Stars: ✭ 127 (+38.04%)
Mutual labels:  gorm
think-pagination
Pagination for ThinkJS 3 & 2
Stars: ✭ 13 (-85.87%)
Mutual labels:  pagination
lightning-data-table
Lightning components for building a data-table with search, column sorting, pagination for Salesforce
Stars: ✭ 15 (-83.7%)
Mutual labels:  pagination
flop
Filtering, ordering and pagination for Ecto
Stars: ✭ 56 (-39.13%)
Mutual labels:  pagination
pagi
A better WordPress pagination.
Stars: ✭ 30 (-67.39%)
Mutual labels:  pagination
Exopite-Multifilter-Multi-Sorter-WordPress-Plugin
Display and/or sort/filter any page or post types by multiple taxonomies or terms (like post by categories and/or tags) with AJAX. Exopite multifilter, multi-sortable, multi selectable, multi filterable sortable Wordpress Plugin.
Stars: ✭ 18 (-80.43%)
Mutual labels:  pagination

gorm-cursor-paginator Build Status Coverage Status Go Report Card

A paginator doing cursor-based pagination based on GORM

This doc is for v2, which uses GORM v2. If you are using GORM v1, please checkout v1 doc.

Features

  • Query extendable.
  • Multiple paging keys.
  • Paging rule customization for each key.
  • GORM column tag supported.
  • Error handling enhancement.
  • Exporting cursor module for advanced usage.

Installation

go get -u github.com/pilagod/gorm-cursor-paginator/v2

Usage By Example

import (
   "github.com/pilagod/gorm-cursor-paginator/v2/paginator"
)

Given an User model for example:

type User struct {
    ID          int
    JoinedAt    time.Time `gorm:"column:created_at"`
}

We first need to create a paginator.Paginator for User, here are some useful patterns:

  1. Configure by paginator.Option, those functions with With prefix are factories for paginator.Option:

    func CreateUserPaginator(
        cursor paginator.Cursor,
        order *paginator.Order,
        limit *int,
    ) *paginator.Paginator {
        opts := []paginator.Option{
            &paginator.Config{
                Keys: []string{"ID", "JoinedAt"},
                Limit: 10,
                Order: paginator.ASC,
            },
        }
        if limit != nil {
            opts = append(opts, paginator.WithLimit(*limit))
        }
        if order != nil {
            opts = append(opts, paginator.WithOrder(*order))
        }
        if cursor.After != nil {
            opts = append(opts, paginator.WithAfter(*cursor.After))
        }
        if cursor.Before != nil {
            opts = append(opts, paginator.WithBefore(*cursor.Before))
        }
        return paginator.New(opts...)
    }
  2. Configure by setters on paginator.Paginator:

    func CreateUserPaginator(
        cursor paginator.Cursor,
        order *paginator.Order,
        limit *int,
    ) *paginator.Paginator {
        p := paginator.New(
            &paginator.Config{
                Keys: []string{"ID", "JoinedAt"},
                Limit: 10,
                Order: paginator.ASC,
            },
        )
        if order != nil {
            p.SetOrder(*order)
        }
        if limit != nil {
            p.SetLimit(*limit)
        }
        if cursor.After != nil {
            p.SetAfter(*cursor.After)
        }
        if cursor.Before != nil {
            p.SetBefore(*cursor.Before)
        }
        return p
    }
  3. Configure by paginator.Rule for fine grained setting for each key:

    Please refer to Specification for details of paginator.Rule.

    func CreateUserPaginator(/* ... */) {
        p := paginator.New(
            &paginator.Config{
                Rules: []paginator.Rule{
                    {
                        Key: "ID",
                    },
                    {
                        Key: "JoinedAt",
                        Order: paginator.DESC,
                        SQLRepr: "users.created_at",
                        NULLReplacement: "1970-01-01",
                    },
                },
                Limit: 10,
                // Order here will apply to keys without order specified.
                // In this example paginator will order by "ID" ASC, "JoinedAt" DESC.
                Order: paginator.ASC, 
            },
        )
        // ...
        return p
    }

After knowing how to setup the paginator, we can start paginating User with GORM:

func FindUsers(db *gorm.DB, query Query) ([]User, paginator.Cursor, error) {
    var users []User

    // extend query before paginating
    stmt := db.
        Select(/* fields */).
        Joins(/* joins */).
        Where(/* queries */)

    // create paginator for User model
    p := CreateUserPaginator(/* config */)

    // find users with pagination
    result, cursor, err := p.Paginate(stmt, &users)

    // this is paginator error, e.g., invalid cursor
    if err != nil {
        return nil, paginator.Cursor{}, err
    }

    // this is gorm error
    if result.Error != nil {
        return nil, paginator.Cursor{}, result.Error
    }

    return users, cursor, nil
}

The second value returned from paginator.Paginator.Paginate is a paginator.Cursor struct, which is same as cursor.Cursor struct:

type Cursor struct {
    After  *string `json:"after" query:"after"`
    Before *string `json:"before" query:"before"`
}

That's all! Enjoy paginating in the GORM world. 🎉

For more paginating examples, please checkout exmaple/main.go and paginator/paginator_paginate_test.go

For manually encoding/decoding cursor exmaples, please checkout cursor/encoding_test.go

Specification

paginator.Paginator

Default options used by paginator when not specified:

  • Keys: []string{"ID"}
  • Limit: 10
  • Order: paginator.DESC

paginator.Rule

  • Key: Field name in target model struct.
  • Order: Order for this key only.
  • SQLRepr: SQL representation used in raw SQL query.

    This is especially useful when you have JOIN or table alias in your SQL query. If SQLRepr is not specified, paginator will get table name from model, plus table key derived by below rules to form the SQL query:

    1. Find GORM tag column on struct field.
    2. If tag not found, convert struct field name to snake case.
  • NULLReplacement(v2.2.0): Replacement for NULL value when paginating by nullable column.

    If you paginate by nullable column, you will encounter NULLS { FIRST | LAST } problems. This option let you decide how to order rows with NULL value. For instance, we can set this value to 1970-01-01 for a nullable date column, to ensure rows with NULL date will be placed at head when order is ASC, or at tail when order is DESC.

Changelog

v2.2.0

v2.1.0

v2.0.1

  • Fix order flip bug when paginating backward, credit to @sylviamoss.

License

© Cyan Ho (pilagod), 2018-NOW

Released under the MIT License

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].