Add pagination support to monger.query DSL

An example:

(with-collection coll
                  (find {})
                  (paginate :page 1 :per-page 3)
                  (sort { :title 1 }))
This commit is contained in:
Michael S. Klishin 2011-11-15 03:44:19 +04:00
parent 9b5eee13e0
commit 3534e579b7
4 changed files with 55 additions and 0 deletions

View file

@ -0,0 +1,6 @@
(ns monger.pagination)
(defn offset-for
[^long page ^long per-page]
(* per-page
(- (max page 1) 1)))

View file

@ -80,6 +80,10 @@
[m]
(merge m { :snapshot true }))
(defn paginate
[m & { :keys [page per-page] :or { page 1 per-page 10 } }]
(merge m { :limit per-page :skip (monger.pagination/offset-for page per-page) }))
(defmacro with-collection
[^String coll & body]
`(binding [*query-collection* (if (string? ~coll)

View file

@ -0,0 +1,14 @@
(ns monger.test.pagination
(:use [clojure.test]
[monger.pagination]))
(deftest test-pagination-offset
(are [a b] (= a b)
0 (offset-for 1 20)
0 (offset-for 1 30)
10 (offset-for 2 10)
13 (offset-for 2 13)
20 (offset-for 3 10)
22 (offset-for 3 11)
21 (offset-for 4 7)
39 (offset-for 4 13)))

View file

@ -178,3 +178,34 @@
result2 (mgcol/find-one-as-map coll { :counter { "$ne" 32 } })]
(is (= doc2 result1))
(is (= doc1 result2))))
;;
;; monger.query DSL features
;;
;; pagination
(deftest query-using-pagination-dsl
(let [coll "docs"
doc1 { :_id (ObjectId.) :title "Clojure" :tags ["functional" "homoiconic" "syntax-oriented" "dsls" "concurrency features" "jvm"] }
doc2 { :_id (ObjectId.) :title "Java" :tags ["object-oriented" "jvm"] }
doc3 { :_id (ObjectId.) :title "Scala" :tags ["functional" "object-oriented" "dsls" "concurrency features" "jvm"] }
doc4 { :_id (ObjectId.) :title "Ruby" :tags ["dynamic" "object-oriented" "dsls" "jvm"] }
doc5 { :_id (ObjectId.) :title "Groovy" :tags ["dynamic" "object-oriented" "dsls" "jvm"] }
doc6 { :_id (ObjectId.) :title "OCaml" :tags ["functional" "static" "dsls"] }
doc7 { :_id (ObjectId.) :title "Haskell" :tags ["functional" "static" "dsls" "concurrency features"] }
- (mgcol/insert-batch coll [doc1 doc2 doc3 doc4 doc5 doc6 doc7])
result1 (with-collection coll
(find {})
(paginate :page 1 :per-page 3)
(sort { :title 1 }))
result2 (with-collection coll
(find {})
(paginate :page 2 :per-page 3)
(sort { :title 1 }))
result3 (with-collection coll
(find {})
(paginate :page 3 :per-page 3)
(sort { :title 1 }))]
(is (= [doc1 doc5 doc7] result1))
(is (= [doc2 doc6 doc4] result2))
(is (= [doc3] result3))))