Merge pull request #62 from timgluz/query_options
Enhancements for tweaking options of dbCursor
This commit is contained in:
commit
3d120456ff
4 changed files with 220 additions and 4 deletions
|
|
@ -24,7 +24,8 @@
|
|||
* http://clojuremongodb.info/articles/deleting.html
|
||||
* http://clojuremongodb.info/articles/aggregation.html"
|
||||
(:refer-clojure :exclude [find remove count drop distinct empty?])
|
||||
(:import [com.mongodb Mongo DB DBCollection WriteResult DBObject WriteConcern DBCursor MapReduceCommand MapReduceCommand$OutputType]
|
||||
(:import [com.mongodb Mongo DB DBCollection WriteResult DBObject WriteConcern
|
||||
DBCursor MapReduceCommand MapReduceCommand$OutputType]
|
||||
[java.util List Map]
|
||||
[clojure.lang IPersistentMap ISeq]
|
||||
org.bson.types.ObjectId)
|
||||
|
|
@ -34,7 +35,6 @@
|
|||
monger.constraints))
|
||||
|
||||
|
||||
|
||||
;;
|
||||
;; API
|
||||
;;
|
||||
|
|
|
|||
105
src/clojure/monger/cursor.clj
Normal file
105
src/clojure/monger/cursor.clj
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
(ns monger.cursor
|
||||
"Helper-functions for dbCursor object:
|
||||
* to initialize new cursor,
|
||||
* for CRUD functionality of options of dbCursor"
|
||||
(:import [com.mongodb DBCursor Bytes]
|
||||
[java.util List Map]
|
||||
[java.lang Integer]
|
||||
[clojure.lang Keyword])
|
||||
(:require [monger.conversion :refer [to-db-object from-db-object as-field-selector]]))
|
||||
|
||||
(defn ^DBCursor make-db-cursor
|
||||
"initializes new db-cursor."
|
||||
([^String collection] (make-db-cursor collection {} {}))
|
||||
([^String collection ^Map ref] (make-db-cursor collection ref {}))
|
||||
([^String collection ^Map ref fields]
|
||||
(.find
|
||||
(.getCollection monger.core/*mongodb-database* (name collection))
|
||||
(to-db-object ref)
|
||||
(as-field-selector fields))))
|
||||
|
||||
(def cursor-options {:awaitdata Bytes/QUERYOPTION_AWAITDATA
|
||||
;;:exhaust Bytes/QUERYOPTION_EXHAUST - not human settable
|
||||
:notimeout Bytes/QUERYOPTION_NOTIMEOUT
|
||||
:oplogreplay Bytes/QUERYOPTION_OPLOGREPLAY
|
||||
:partial Bytes/QUERYOPTION_PARTIAL
|
||||
:slaveok Bytes/QUERYOPTION_SLAVEOK
|
||||
:tailable Bytes/QUERYOPTION_TAILABLE})
|
||||
|
||||
(defn get-options
|
||||
"Returns map of cursor's options with current state."
|
||||
[^DBCursor db-cur]
|
||||
(into {}
|
||||
(for [[opt option-mask] cursor-options]
|
||||
[opt (< 0 (bit-and (.getOptions db-cur) option-mask))])))
|
||||
|
||||
(defn add-option! [^DBCursor db-cur, ^String opt]
|
||||
(.addOption db-cur (get cursor-options (keyword opt) 0)))
|
||||
|
||||
(defn remove-option! [^DBCursor db-cur, ^String opt]
|
||||
(.setOptions db-cur (bit-and-not (.getOptions db-cur)
|
||||
(get cursor-options (keyword opt) 0))))
|
||||
|
||||
(defmulti add-options (fn [db-cur opts] (class opts)))
|
||||
(defmethod add-options Map [^DBCursor db-cur options]
|
||||
"Changes options by using map of settings, which key specifies name of settings
|
||||
and boolean value specifies new state of the setting.
|
||||
usage:
|
||||
(add-options db-cur {:notimeout true, :tailable false})
|
||||
returns:
|
||||
^DBCursor object."
|
||||
(doseq [[opt value] (seq options)]
|
||||
(if (= true value)
|
||||
(add-option! db-cur opt)
|
||||
(remove-option! db-cur opt)))
|
||||
db-cur)
|
||||
|
||||
(defmethod add-options List [^DBCursor db-cur options]
|
||||
"Takes list of options and activates these options
|
||||
usage:
|
||||
(add-options db-cur [:notimeout :tailable])
|
||||
returns:
|
||||
^DBCursor object"
|
||||
(doseq [opt (seq options)]
|
||||
(add-option! db-cur opt))
|
||||
db-cur)
|
||||
|
||||
(defmethod add-options Integer [^DBCursor db-cur, option]
|
||||
"Takes com.mongodb.Byte value and adds it to current settings.
|
||||
usage:
|
||||
(add-options db-cur com.mongodb.Bytes/QUERYOPTION_NOTIMEOUT)
|
||||
returns:
|
||||
^DBCursor object"
|
||||
(.addOption db-cur option)
|
||||
db-cur)
|
||||
|
||||
(defmethod add-options Keyword [^DBCursor db-cur, option]
|
||||
"Takes just one keyword as name of settings and applies it to the db-cursor.
|
||||
usage:
|
||||
(add-options db-cur :notimeout)
|
||||
returns:
|
||||
^DBCursor object"
|
||||
(add-option! db-cur option)
|
||||
db-cur)
|
||||
|
||||
(defmethod add-options :default [^DBCursor db-cur, options]
|
||||
"Using add-options with not supported type of options just passes unchanged cursor"
|
||||
db-cur)
|
||||
|
||||
(defn ^DBCursor reset-options
|
||||
"Resets cursor options to default value and returns cursor"
|
||||
[^DBCursor db-cur]
|
||||
(.resetOptions db-cur)
|
||||
db-cur)
|
||||
|
||||
(defmulti format-as (fn [db-cur as] as))
|
||||
|
||||
(defmethod format-as :map [db-cur as]
|
||||
(map #(from-db-object %1 true) db-cur))
|
||||
|
||||
(defmethod format-as :seq [db-cur as]
|
||||
(seq db-cur))
|
||||
|
||||
(defmethod format-as :default [db-cur as]
|
||||
db-cur)
|
||||
|
||||
|
|
@ -14,7 +14,8 @@
|
|||
monger.query
|
||||
(:refer-clojure :exclude [select find sort])
|
||||
(:require [monger.core]
|
||||
[monger.internal pagination])
|
||||
[monger.internal pagination]
|
||||
[monger.cursor :as cursor :refer [add-options]])
|
||||
(:import [com.mongodb DB DBCollection DBObject DBCursor ReadPreference]
|
||||
[java.util List])
|
||||
(:use [monger conversion operators]))
|
||||
|
|
@ -75,7 +76,7 @@
|
|||
(when read-preference
|
||||
(.setReadPreference cursor read-preference))
|
||||
(when options
|
||||
(.setOptions cursor options))
|
||||
(add-options cursor options))
|
||||
(map (fn [x] (from-db-object x keywordize-fields))
|
||||
cursor)))
|
||||
|
||||
|
|
|
|||
110
test/monger/test/cursor_test.clj
Normal file
110
test/monger/test/cursor_test.clj
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
(set! *warn-on-reflection* true)
|
||||
|
||||
(ns monger.test.cursor-test
|
||||
(:import [com.mongodb DBCursor DBObject Bytes]
|
||||
[java.util List Map])
|
||||
(:require [monger.test.helper :as helper])
|
||||
(:use clojure.test
|
||||
monger.cursor
|
||||
monger.test.fixtures))
|
||||
|
||||
(helper/connect!)
|
||||
|
||||
(deftest make-db-cursor-for-collection
|
||||
(is (= DBCursor
|
||||
(class (make-db-cursor :docs)))))
|
||||
|
||||
(deftest getting-cursor-options-value
|
||||
(let [db-cur (make-db-cursor :docs)
|
||||
opts (get-options db-cur)]
|
||||
(is (= true (isa? (class opts) Map)))
|
||||
(is (= 0 (.getOptions db-cur))) ;;test default value
|
||||
(is (= false (:notimeout opts)))
|
||||
(is (= false (:partial opts)))
|
||||
(is (= false (:awaitdata opts)))
|
||||
(is (= false (:oplogreplay opts)))
|
||||
(is (= false (:slaveok opts)))
|
||||
(is (= false (:tailable opts)))))
|
||||
|
||||
(deftest adding-option-to-cursor
|
||||
(let [db-cur (make-db-cursor :docs)
|
||||
_ (add-option! db-cur :notimeout)]
|
||||
(is (= (:notimeout cursor-options)
|
||||
(.getOptions db-cur)))
|
||||
(add-option! db-cur :tailable)
|
||||
(is (= (.getOptions db-cur)
|
||||
(bit-or (:notimeout cursor-options)
|
||||
(:tailable cursor-options))))))
|
||||
|
||||
(deftest remove-option-from-cursor
|
||||
(let [db-cur (make-db-cursor :docs)]
|
||||
(add-option! db-cur :partial)
|
||||
(add-option! db-cur :awaitdata)
|
||||
;; removing not-set option should not affect result
|
||||
(remove-option! db-cur :notimeout)
|
||||
(is (= (.getOptions db-cur)
|
||||
(bit-or (:partial cursor-options)
|
||||
(:awaitdata cursor-options))))
|
||||
;; removing active option should remove correct value
|
||||
(remove-option! db-cur :awaitdata)
|
||||
(is (= (.getOptions db-cur)
|
||||
(:partial cursor-options)))))
|
||||
|
||||
|
||||
(deftest test-reset-options
|
||||
(let [db-cur (make-db-cursor :docs)]
|
||||
(add-option! db-cur :partial)
|
||||
(is (= (.getOptions db-cur)
|
||||
(:partial cursor-options)))
|
||||
(is (= 0
|
||||
(int (.getOptions (reset-options db-cur)))))))
|
||||
|
||||
(deftest add-options-with-hashmap
|
||||
(let [db-cur (make-db-cursor :docs)
|
||||
_ (add-options db-cur {:notimeout true :slaveok true})
|
||||
opts (get-options db-cur)]
|
||||
(is (= true (:notimeout opts)))
|
||||
(is (= true (:slaveok opts)))
|
||||
(is (= false (:tailable opts)))
|
||||
(is (= false (:oplogreplay opts)))))
|
||||
|
||||
(deftest add-options-with-hashmap-and-remove-option
|
||||
(let [db-cur (make-db-cursor :docs)
|
||||
_ (add-options db-cur {:notimeout true :slaveok true})
|
||||
opts (get-options db-cur)]
|
||||
(is (= true (:notimeout opts)))
|
||||
(is (= true (:slaveok opts)))
|
||||
;;remove key and add another option
|
||||
(add-options db-cur {:partial true :slaveok false})
|
||||
(let [opts (get-options db-cur)]
|
||||
(is (= true (:notimeout opts)))
|
||||
(is (= true (:partial opts)))
|
||||
(is (= false (:slaveok opts)))
|
||||
(is (= false (:tailable opts))))))
|
||||
|
||||
(deftest add-options-with-list
|
||||
(let [db-cur (make-db-cursor :docs)
|
||||
_ (add-options db-cur [:notimeout :slaveok])
|
||||
opts (get-options db-cur)]
|
||||
(is (= true (:notimeout opts)))
|
||||
(is (= true (:slaveok opts)))
|
||||
(is (= false (:tailable opts)))
|
||||
(is (= false (:oplogreplay opts)))))
|
||||
|
||||
(deftest add-options-with-Bytes
|
||||
(let [db-cur (make-db-cursor :docs)
|
||||
_ (add-options db-cur Bytes/QUERYOPTION_NOTIMEOUT)
|
||||
opts (get-options db-cur)]
|
||||
(is (= true (:notimeout opts)))
|
||||
(is (= false (:slaveok opts)))
|
||||
(is (= false (:tailable opts)))
|
||||
(is (= false (:oplogreplay opts)))))
|
||||
|
||||
(deftest add-options-with-one-keyword
|
||||
(let [db-cur (make-db-cursor :docs)
|
||||
_ (add-options db-cur :notimeout)
|
||||
opts (get-options db-cur)]
|
||||
(is (= true (:notimeout opts)))
|
||||
(is (= false (:slaveok opts)))
|
||||
(is (= false (:tailable opts)))
|
||||
(is (= false (:oplogreplay opts)))))
|
||||
Loading…
Reference in a new issue