-
Notifications
You must be signed in to change notification settings - Fork 5
/
pagination.clj
59 lines (54 loc) · 1.74 KB
/
pagination.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
(ns ductile.pagination
(:require [schema.core :as s]))
(def default-limit 100)
;; https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules.html#dynamic-index-settings
(def max-result-window 10000)
(defn list-response-schema
"generate a list response schema for a model"
[Model]
{:data [Model]
:paging {s/Any s/Any}})
(defn response
"Make a paginated response adding pagination helpers into a map"
[results
{:keys [offset
limit
sort
search_after
total-hits]}]
(let [offset (or offset 0)
limit (or limit default-limit)
previous-offset (- offset limit)
next-offset (+ offset limit)
previous? (and (not search_after)
(pos? offset)
(> max-result-window (+ offset limit)))
next? (if search_after
(= limit (count results))
(> total-hits next-offset))
previous {:previous {:limit limit
:offset (if (> previous-offset 0)
previous-offset 0)}}
next {:next
(cond->
{:limit limit
:offset next-offset}
sort (assoc :search_after sort))}]
{:data results
:paging (merge
{:total-hits total-hits}
(when previous? previous)
(when next? next)
(when sort {:sort sort}))}))
(defn paginate
[data {:keys [sort_by sort_order offset limit]
:or {sort_by :id
sort_order :asc
offset 0
limit default-limit}}]
(as-> data $
(sort-by sort_by $)
(if (= :desc sort_order)
(reverse $) $)
(drop offset $)
(take limit $)))