diff --git a/src/monger/pagination.clj b/src/monger/pagination.clj new file mode 100644 index 0000000..a792373 --- /dev/null +++ b/src/monger/pagination.clj @@ -0,0 +1,6 @@ +(ns monger.pagination) + +(defn offset-for + [^long page ^long per-page] + (* per-page + (- (max page 1) 1))) diff --git a/src/monger/query.clj b/src/monger/query.clj index 2362e0e..5812722 100644 --- a/src/monger/query.clj +++ b/src/monger/query.clj @@ -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) diff --git a/test/monger/test/pagination.clj b/test/monger/test/pagination.clj new file mode 100644 index 0000000..b8ba8ae --- /dev/null +++ b/test/monger/test/pagination.clj @@ -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))) diff --git a/test/monger/test/querying.clj b/test/monger/test/querying.clj index bc464ee..1732294 100644 --- a/test/monger/test/querying.clj +++ b/test/monger/test/querying.clj @@ -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))))