Add monger.collection/find-and-modify and associated tests.

This commit is contained in:
Baishampayan Ghose 2012-05-12 09:02:19 +05:30
parent 2228a6dcbe
commit ccd3d7ab66
2 changed files with 83 additions and 0 deletions

View file

@ -172,6 +172,42 @@
(from-db-object ^DBObject (find-one collection ref fields) keywordize)))
;;
;; monger.collection/find-and-modify
;;
(defn ^DBObject find-and-modify
"Atomically modify a document (at most one) and return it.
EXAMPLES:
;; Find and modify a document
(mgcol/find-and-modify collection { :language \"Python\" } { :language \"Clojure\" })
;; If multiple documents match, choose the first one in the specified order
(mgcol/find-and-modify collection { :language \"Python\" } { :language \"Clojure\" } :sort { :language -1 })
;; Remove the object before returning
(mgcol/find-and-modify collection { :language \"Python\" } {} :remove true)
;; Return the modified object instead of the old one
(mgcol/find-and-modify collection { :language \"Python\" } { :language \"Clojure\" } :return-new true)
;; Retrieve a subset of fields
(mgcol/find-and-modify collection { :language \"Python\" } { :language \"Clojure\" } :fields [ :language ])
;; Create the object if it doesn't exist
(mgcol/find-and-modify collection { :language \"Factor\" } { :language \"Clojure\" } :upsert true)
"
([^String collection ^Map conditions ^Map document & { :keys [fields sort remove return-new upsert keywordize] :or
{ fields nil sort nil remove false return-new false upsert false keywordize true }}]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)
maybe-fields (when fields (to-db-object (as-field-selector fields)))
maybe-sort (when sort (to-db-object sort))]
(from-db-object
^DBObject (.findAndModify ^DBCollection coll ^DBObject (to-db-object conditions) maybe-fields maybe-sort remove
^DBObject (to-db-object document) return-new upsert) keywordize))))
;;
;; monger.collection/find-by-id

View file

@ -291,3 +291,50 @@
(mgcol/insert coll { :_id oid :title title :measurements v })
(mgcol/update coll { :_id oid } { $rename { :measurements "results" } })
(is (= { :_id oid :title title :results v } (mgcol/find-map-by-id coll oid)))))
;;
;; find-and-modify
;;
(deftest find-and-modify-a-single-document
(let [coll "docs"
oid (ObjectId.)
doc {:_id oid :name "Sophie Bangs" :level 42}
conditions {:name "Sophie Bangs"}
update {$inc {:level 1}}]
(mgcol/insert coll doc)
(let [res (mgcol/find-and-modify coll conditions update :return-new true)]
(is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 43})))))
(deftest find-and-modify-remove-a-document
(let [coll "docs"
oid (ObjectId.)
doc {:_id oid :name "Sophie Bangs" :level 42}
conditions {:name "Sophie Bangs"}]
(mgcol/insert coll doc)
(let [res (mgcol/find-and-modify coll conditions {} :remove true)]
(is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 42}))
(is (empty? (mgcol/find-maps coll conditions))))))
(deftest find-and-modify-upsert-a-document
(let [coll "docs"
oid (ObjectId.)
doc {:_id oid :name "Sophie Bangs" :level 42}]
(let [res (mgcol/find-and-modify coll doc doc :upsert true)]
(is (empty? res))
(is (select-keys (mgcol/find-map-by-id coll oid) [:name :level]) (dissoc doc :_id)))))
(deftest find-and-modify-after-sort
(let [coll "docs"
oid (ObjectId.)
oid2 (ObjectId.)
doc {:name "Sophie Bangs"}
doc1 (assoc doc :_id oid :level 42)
doc2 (assoc doc :_id oid2 :level 0)]
(mgcol/insert-batch coll [doc1 doc2])
(let [res (mgcol/find-and-modify coll doc {$inc {:level 1}} :sort {:level -1})]
(is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 42})))))