diff options
Diffstat (limited to 'internal')
-rw-r--r-- | internal/components/data.go | 9 | ||||
-rw-r--r-- | internal/index/search.go | 9 | ||||
-rw-r--r-- | internal/pagination/pagination.go | 31 | ||||
-rw-r--r-- | internal/server/mux.go | 54 |
4 files changed, 71 insertions, 32 deletions
diff --git a/internal/components/data.go b/internal/components/data.go index 3625017..aecd44c 100644 --- a/internal/components/data.go +++ b/internal/components/data.go @@ -21,9 +21,8 @@ type TemplateData struct { type ResultData struct { TemplateData - Query string - ResultsPerPage int - Results *search.Result - Prev string - Next string + Query string + Results *search.Result + Prev string + Next string } diff --git a/internal/index/search.go b/internal/index/search.go index d576d5a..9d77488 100644 --- a/internal/index/search.go +++ b/internal/index/search.go @@ -15,7 +15,7 @@ import ( "github.com/pkg/errors" ) -const ResultsPerPage = 100 +const DefaultPageSize = 100 type DocumentMatch struct { *search.DocumentMatch @@ -134,7 +134,8 @@ func (index *ReadIndex) Search( ctx context.Context, source *config.Source, keyword string, - from uint64, + from int, + pageSize int, ) (*Result, error) { query := bleve.NewBooleanQuery() @@ -175,10 +176,10 @@ func (index *ReadIndex) Search( search := bleve.NewSearchRequest(query) search.Explain = config.DevMode - search.Size = ResultsPerPage + search.Size = pageSize if from != 0 { - search.From = int(from) + search.From = from } return index.search(ctx, search) diff --git a/internal/pagination/pagination.go b/internal/pagination/pagination.go new file mode 100644 index 0000000..4d41587 --- /dev/null +++ b/internal/pagination/pagination.go @@ -0,0 +1,31 @@ +package pagination + +type Pagination struct { + total uint64 + + From int + + Size, + Current, + Prev, + Next int + + Needed bool +} + +func New(page int, pageSize int) *Pagination { + return &Pagination{ + Current: page, + From: (page - 1) * pageSize, + Size: pageSize, + } +} + +func (p *Pagination) SetResults(total uint64) { + p.total = total + p.Needed = p.total > uint64(p.Size) + if uint64(p.Current*p.Size) <= p.total { + p.Next = p.Current + 1 + p.Prev = p.Current - 1 + } +} diff --git a/internal/server/mux.go b/internal/server/mux.go index 66da7b5..80c68cb 100644 --- a/internal/server/mux.go +++ b/internal/server/mux.go @@ -16,6 +16,7 @@ import ( "go.alanpearce.eu/searchix/internal/config" search "go.alanpearce.eu/searchix/internal/index" "go.alanpearce.eu/searchix/internal/opensearch" + "go.alanpearce.eu/searchix/internal/pagination" "go.alanpearce.eu/x/log" sentryhttp "github.com/getsentry/sentry-go/http" @@ -104,17 +105,19 @@ func NewMux( if r.URL.Query().Has("query") { qs := r.URL.Query().Get("query") - pg := r.URL.Query().Get("page") - var page uint64 = 1 - if pg != "" { - page, err = strconv.ParseUint(pg, 10, 64) - if err != nil || page == 0 { + + var pageSize int = search.DefaultPageSize + var pageNumber = 1 + if pg := r.URL.Query().Get("page"); pg != "" { + pageNumber, err = strconv.Atoi(pg) + if err != nil || pageNumber <= 0 || pageNumber > math.MaxInt { errorHandler(w, r, "Bad query string", http.StatusBadRequest) return } } - results, err := index.Search(ctx, source, qs, (page-1)*search.ResultsPerPage) + page := pagination.New(pageNumber, pageSize) + results, err := index.Search(ctx, source, qs, page.From, page.Size) if err != nil { if err == context.DeadlineExceeded { errorHandler(w, r, "Search timed out", http.StatusInternalServerError) @@ -135,13 +138,25 @@ func NewMux( Assets: frontend.Assets, Query: qs, }, - ResultsPerPage: search.ResultsPerPage, - Query: qs, - Results: results, + Query: qs, + Results: results, } - hits := uint64(len(results.Hits)) - if results.Total > hits { + page.SetResults(results.Total) + log.Debug( + "pag", + "needed", + page.Needed, + "current", + page.Current, + "total", + results.Total, + "next", + page.Next, + "prev", + page.Prev, + ) + if page.Needed { q, err := url.ParseQuery(r.URL.RawQuery) if err != nil { errorHandler(w, r, "Query string error", http.StatusBadRequest) @@ -149,23 +164,16 @@ func NewMux( return } - if page > uint64(math.Ceil(float64(results.Total)/search.ResultsPerPage)) { - errorHandler(w, r, "Not found", http.StatusNotFound) - - return - } - - if page*search.ResultsPerPage < results.Total { - q.Set("page", strconv.FormatUint(page+1, 10)) + if page.Next != 0 { + q.Set("page", strconv.Itoa(page.Next)) tdata.Next = "search?" + q.Encode() } - if page > 1 { - p := page - 1 - if p == 1 { + if page.Prev != 0 { + if page.Prev == 1 { q.Del("page") } else { - q.Set("page", strconv.FormatUint(p, 10)) + q.Set("page", strconv.Itoa(page.Prev)) } tdata.Prev = "search?" + q.Encode() } |