Introduce monger.collection/insert-and-return

Per discussion in Raynes/refheap#89
This commit is contained in:
Michael S. Klishin 2012-06-30 23:49:23 +04:00
parent 8f8b4387b6
commit 080ef6b896
3 changed files with 87 additions and 7 deletions

View file

@ -1,6 +1,26 @@
## Changes between 1.0.0-alpha3 and 1.1.0-alpha4
No changes yet.
### monger.collection/insert-and-return
`monger.collection/insert-and-return` is a new function that solves the biggest complain about Monger's `monger.collection/insert` behavior
from Monger 1.0 users. Because `monger.collection/insert` returns a write result and is supposed to be used with Validateur and
`monger.result/ok?` and similar functions, it is hard to retrieve object id in case it wasn't explicitly passed in.
This resulted in code that looks more or less like this:
``` clojure
(let [oid (ObjectId.)
result (merge doc {:_id oid)]
(monger.collection/insert "documents" result)
result)
```
To solve this problem, we introduce a new function, `monger.collection/insert-and-return`, that returns the exact inserted document
as an immutable Clojure map. The `:_id` key will be available on the returned map, even if wasn't present and had to be generated.
`monger.collection/insert` behavior stays the same both because of backwards compatibility concerns and because there are valid cases
when a user may want to have the write result returned.
## Changes between 1.0.0-alpha2 and 1.1.0-alpha3

View file

@ -50,10 +50,14 @@
;;
(defn ^WriteResult insert
"Saves @document@ to @collection@. You can optionally specify WriteConcern.
"Saves @document@ to @collection@ and returns write result monger.result/ok? and similar functions operate on. You can optionally specify WriteConcern.
In case you need the exact inserted document returned, with the :_id key generated, use monger.collection/insert-and-return
instead.
EXAMPLES:
;; returns write result
(monger.collection/insert \"people\" {:name \"Joe\", :age 30})
(monger.collection/insert \"people\" {:name \"Joe\", :age 30, WriteConcern/SAFE})
@ -64,14 +68,40 @@
^WriteConcern monger.core/*mongodb-write-concern*))
([^String collection document ^WriteConcern concern]
(.insert (.getCollection monger.core/*mongodb-database* collection)
(to-db-object document)
concern))
(to-db-object document)
concern))
([^DB db ^String collection document ^WriteConcern concern]
(.insert (.getCollection db collection)
(to-db-object document)
concern)))
(defn ^clojure.lang.IPersistentMap insert-and-return
"Like monger.collection/insert but returns the inserted document as a persistent Clojure map.
If the :_id key wasn't set on the document, it will be generated and merged into the returned map.
EXAMPLES:
;; returns the entire document with :_id generated
(monger.collection/insert-and-return \"people\" {:name \"Joe\", :age 30})
(monger.collection/insert-and-return \"people\" {:name \"Joe\", :age 30, WriteConcern/SAFE})
"
([^String collection document]
(insert-and-return ^DB monger.core/*mongodb-database* collection document ^WriteConcern monger.core/*mongodb-write-concern*))
([^String collection document ^WriteConcern concern]
(insert-and-return ^DB monger.core/*mongodb-database* collection document concern))
([^DB db ^String collection document ^WriteConcern concern]
;; MongoDB Java driver will generate the _id and set it but it tries to mutate the inserted DBObject
;; and it does not work very well in our case, because that DBObject is short lived and produced
;; from the Clojure map we are passing in. Plus, this approach is very awkward with immutable data
;; structures being the default. MK.
(let [doc (merge document {:_id (ObjectId.)})]
(insert db collection doc concern)
doc)))
(defn ^WriteResult insert-batch
"Saves @documents@ do @collection@. You can optionally specify WriteConcern as a third argument.
@ -92,8 +122,8 @@
concern))
([^DB db ^String collection ^List documents ^WriteConcern concern]
(.insert (.getCollection db collection)
^List (to-db-object documents)
concern)))
^List (to-db-object documents)
concern)))
;;
;; monger.collection/find
@ -220,7 +250,7 @@
"
([^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}}]
{fields nil sort nil remove false return-new false upsert false keywordize true}}]
(let [coll (.getCollection monger.core/*mongodb-database* collection)
maybe-fields (when fields (as-field-selector fields))
maybe-sort (when sort (to-db-object sort))]

View file

@ -101,6 +101,36 @@
(is (= dbref fo)))))
;;
;; insert-and-return
;;
(deftest insert-and-return-a-basic-document-without-id-and-with-default-write-concern
(let [collection "people"
doc {:name "Joe" :age 30}
result (mc/insert-and-return "people" doc)]
(is (= (:name doc)
(:name result)))
(is (= (:age doc)
(:age result)))
(is (:_id result))
(is (= 1 (mc/count collection)))))
(deftest insert-and-return-a-basic-document-without-id-but-with-a-write-concern
(let [collection "people"
doc {:name "Joe" :age 30 :ratio 3/4}
result (mc/insert-and-return "people" doc WriteConcern/FSYNC_SAFE)]
(is (= (:name doc)
(:name result)))
(is (= (:age doc)
(:age result)))
(is (= (:ratio doc)
(:ratio result)))
(is (:_id result))
(is (= 1 (mc/count collection)))))
;;
;; insert-batch
;;