Added docs, improved test suite.

Removed (seq) method call from find-maps, since DBCursor implements Iterable interface. 
Added empty? method for collection.
This commit is contained in:
Oleksandr Petrov 2011-12-23 11:56:14 +01:00
parent 3357179659
commit 1a8eb1ef80
2 changed files with 126 additions and 37 deletions

View file

@ -24,7 +24,14 @@
;; ;;
(defn ^WriteResult insert (defn ^WriteResult insert
"Saves document to database" "Saves @document@ to @collection@. You can optionally specify WriteConcern.
EXAMPLES:
(monger.collection/insert \"people\" { :name \"Joe\", :age 30 })
(monger.collection/insert \"people\" { :name \"Joe\", :age 30, WriteConcern/SAFE })
"
([^String collection, ^DBObject document] ([^String collection, ^DBObject document]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)] (let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)]
(.insert ^DBCollection coll ^DBObject (to-db-object document) ^WriteConcern monger.core/*mongodb-write-concern*))) (.insert ^DBCollection coll ^DBObject (to-db-object document) ^WriteConcern monger.core/*mongodb-write-concern*)))
@ -34,7 +41,15 @@
(defn ^WriteResult insert-batch (defn ^WriteResult insert-batch
"Saves documents do database" "Saves @documents@ do @collection@. You can optionally specify WriteConcern as a third argument.
EXAMPLES:
(monger.collection/insert-batch \"people\" [{ :name \"Joe\", :age 30 }, { :name \"Paul\", :age 27 }])
(monger.collection/insert-batch \"people\" [{ :name \"Joe\", :age 30 }, { :name \"Paul\", :age 27 }] WriteConcern/NORMAL)
"
([^String collection, ^List documents] ([^String collection, ^List documents]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)] (let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)]
(.insert ^DBCollection coll ^List (to-db-object documents) ^WriteConcern monger.core/*mongodb-write-concern*))) (.insert ^DBCollection coll ^List (to-db-object documents) ^WriteConcern monger.core/*mongodb-write-concern*)))
@ -48,7 +63,20 @@
(declare fields-to-db-object) (declare fields-to-db-object)
(defn ^DBCursor find (defn ^DBCursor find
"Queries for an object in this collection." "Queries for objects in this collection.
This function returns DBCursor, which allows you to iterate over DBObjects.
If you want to manipulate clojure sequences maps, please @find-maps@.
EXAMPLES:
;; return all objects in this collection.
(mgcol/find \"people\")
;; return all objects matching query
(mgcol/find \"people\" { :company \"Comp Corp\"})
;; return all objects matching query, taking only specified fields
(mgcol/find \"people\" { :company \"Comp Corp\"} [:first_name :last_name])
"
([^String collection] ([^String collection]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)] (let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)]
(.find coll))) (.find coll)))
@ -58,29 +86,22 @@
([^String collection, ^Map ref, ^List fields] ([^String collection, ^Map ref, ^List fields]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection) (let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)
map-of-fields (fields-to-db-object fields)] map-of-fields (fields-to-db-object fields)]
(.find ^DBCollection coll ^DBObject (to-db-object ref) ^DBObject (to-db-object map-of-fields)))) (.find ^DBCollection coll ^DBObject (to-db-object ref) ^DBObject (to-db-object map-of-fields)))))
([^String collection, ^Map ref, ^List fields, num-to-skip, limit]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)
map-of-fields (fields-to-db-object fields)]
(.find ^DBCollection coll ^DBObject (to-db-object ref) ^DBObject (to-db-object map-of-fields) ^long num-to-skip ^long limit)))
([^String collection, ^Map ref, ^List fields, num-to-skip, batch-size, limit]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)
map-of-fields (fields-to-db-object fields)]
(.find ^DBCollection coll ^DBObject (to-db-object ref) ^DBObject (to-db-object map-of-fields) ^long num-to-skip ^long batch-size ^long limit))))
(defn ^ISeq find-maps (defn ^ISeq find-maps
"Queries for objects in this collection.
This function returns clojure Seq of Maps.
If you want to work directly with DBObject, use find.
"
([^String collection] ([^String collection]
(map (fn [x] (from-db-object x true)) (seq (find collection)))) (map (fn [x] (from-db-object x true)) (find collection)))
([^String collection, ^Map ref] ([^String collection, ^Map ref]
(map (fn [x] (from-db-object x true)) (seq (find collection ref)))) (map (fn [x] (from-db-object x true)) (find collection ref)))
([^String collection, ^Map ref, ^List fields] ([^String collection, ^Map ref, ^List fields]
(map (fn [x] (from-db-object x true)) (seq (find collection ref fields)))) (map (fn [x] (from-db-object x true)) (find collection ref fields))))
([^String collection, ^Map ref, ^List fields, num-to-skip, limit]
(map (fn [x] (from-db-object x true)) (seq (find collection ref fields num-to-skip limit))))
([^String collection, ^Map ref, ^List fields, num-to-skip, batch-size, limit]
(map (fn [x] (from-db-object x true)) (seq (find collection ref fields num-to-skip batch-size limit)))))
(defn ^ISeq find-seq (defn ^ISeq find-seq
"Queries for objects in this collection, returns ISeq of DBObjects."
([^String collection] ([^String collection]
(seq (find collection))) (seq (find collection)))
([^String collection, ^Map ref] ([^String collection, ^Map ref]
@ -93,7 +114,17 @@
;; ;;
(defn ^DBObject find-one (defn ^DBObject find-one
"Returns a single object from this collection matching the query." "Returns a single DBObject from this collection matching the query.
EXAMPLES:
(mgcol/find-one collection { :language \"Clojure\" })
;; Return only :language field.
;; Note that _id field is always returned.
(mgcol/find-one collection { :language \"Clojure\" } [:language])
"
([^String collection, ^Map ref] ([^String collection, ^Map ref]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)] (let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)]
(.findOne ^DBCollection coll ^DBObject (to-db-object ref)))) (.findOne ^DBCollection coll ^DBObject (to-db-object ref))))
@ -103,6 +134,7 @@
(.findOne ^DBCollection coll ^DBObject (to-db-object ref) ^DBObject (to-db-object map-of-fields))))) (.findOne ^DBCollection coll ^DBObject (to-db-object ref) ^DBObject (to-db-object map-of-fields)))))
(defn ^IPersistentMap find-one-as-map (defn ^IPersistentMap find-one-as-map
"Returns a single object converted to Map from this collection matching the query."
([^String collection, ^Map ref] ([^String collection, ^Map ref]
(from-db-object ^DBObject (find-one collection ref) true)) (from-db-object ^DBObject (find-one collection ref) true))
([^String collection, ^Map ref, keywordize] ([^String collection, ^Map ref, keywordize]
@ -117,12 +149,23 @@
;; ;;
(defn ^DBObject find-by-id (defn ^DBObject find-by-id
"Returns a single object with matching _id field.
EXAMPLES:
(mgcol/find-one-by-id collection \"4ef45ab4744e9fd632640e2d\")
;; Return only :language field.
;; Note that _id field is always returned.
(mgcol/find-one-by-id collection \"4ef45ab4744e9fd632640e2d\" [:language])
"
([^String collection, id] ([^String collection, id]
(find-one collection { :_id id })) (find-one collection { :_id id }))
([^String collection, id, ^List fields] ([^String collection, id, ^List fields]
(find-one collection { :_id id } fields))) (find-one collection { :_id id } fields)))
(defn ^IPersistentMap find-map-by-id (defn ^IPersistentMap find-map-by-id
"Returns a single object, converted to map with matching _id field."
([^String collection, id] ([^String collection, id]
(from-db-object ^DBObject (find-one-as-map collection { :_id id }) true)) (from-db-object ^DBObject (find-one-as-map collection { :_id id }) true))
([^String collection, id, keywordize] ([^String collection, id, keywordize]
@ -158,12 +201,30 @@
(.count coll (to-db-object conditions))))) (.count coll (to-db-object conditions)))))
(defn any? (defn any?
"Wether the collection has any items at all, or items matching query.
EXAMPLES:
;; wether the collection has any items
(mgcol/any? collection)
(mgcol/any? collection { :language \"Clojure\" }))
"
([^String collection] ([^String collection]
(> (count collection) 0)) (> (count collection) 0))
([^String collection, ^Map conditions] ([^String collection, ^Map conditions]
(> (count collection conditions) 0))) (> (count collection conditions) 0)))
(defn empty?
"Wether the collection is empty.
EXAMPLES:
(mgcol/empty? \"things\")
"
([^String collection]
(= (count collection) 0)))
;; monger.collection/update ;; monger.collection/update
(defn ^WriteResult update (defn ^WriteResult update
@ -306,11 +367,13 @@
;; ;;
(defn drop-index (defn drop-index
"Drops an index from this collection."
[^String collection, ^String name] [^String collection, ^String name]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)] (let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)]
(.dropIndex coll name))) (.dropIndex coll name)))
(defn drop-indexes (defn drop-indexes
"Drops an indices from this collection."
[^String collection] [^String collection]
(.dropIndexes ^DBCollection (.getCollection monger.core/*mongodb-database* collection))) (.dropIndexes ^DBCollection (.getCollection monger.core/*mongodb-database* collection)))
@ -331,6 +394,7 @@
(.collectionExists monger.core/*mongodb-database* collection)) (.collectionExists monger.core/*mongodb-database* collection))
(defn create (defn create
"Creates a collection with a given name and options."
[^String collection, ^Map options] [^String collection, ^Map options]
(.createCollection monger.core/*mongodb-database* collection (to-db-object options))) (.createCollection monger.core/*mongodb-database* collection (to-db-object options)))
@ -364,6 +428,7 @@
;; ;;
(defn map-reduce (defn map-reduce
"Performs a map reduce operation"
([^String collection, ^String js-mapper, ^String js-reducer, ^String output, ^Map query] ([^String collection, ^String js-mapper, ^String js-reducer, ^String output, ^Map query]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)] (let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)]
(.mapReduce coll js-mapper js-reducer output (to-db-object query)))) (.mapReduce coll js-mapper js-reducer output (to-db-object query))))
@ -377,6 +442,7 @@
;; ;;
(defn distinct (defn distinct
"Finds distinct values for a key"
([^String collection, ^String key] ([^String collection, ^String key]
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)] (let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)]
(.distinct coll ^String (to-db-object key)))) (.distinct coll ^String (to-db-object key))))

View file

@ -114,21 +114,6 @@
(is (= 1 (mgcol/count collection))))) (is (= 1 (mgcol/count collection)))))
;;
;; find
;;
(deftest find-full-document-when-collection-is-empty
(let [collection "docs"
cursor (mgcol/find collection)]
(is (empty? (iterator-seq cursor)))))
(deftest find-document-seq-when-collection-is-empty
(let [collection "docs"]
(is (empty? (mgcol/find-seq collection)))))
;; ;;
;; find-one ;; find-one
;; ;;
@ -152,7 +137,6 @@
(is (= (mgcnv/from-db-object found-one true) doc)) (is (= (mgcnv/from-db-object found-one true) doc))
(is (= (mgcnv/to-db-object doc) found-one)))) (is (= (mgcnv/to-db-object doc) found-one))))
(deftest find-one-full-document-as-map-when-collection-has-matches (deftest find-one-full-document-as-map-when-collection-has-matches
(let [collection "docs" (let [collection "docs"
doc-id (monger.util/random-uuid) doc-id (monger.util/random-uuid)
@ -252,6 +236,15 @@
;; find ;; find
;; ;;
(deftest find-full-document-when-collection-is-empty
(let [collection "docs"
cursor (mgcol/find collection)]
(is (empty? (iterator-seq cursor)))))
(deftest find-document-seq-when-collection-is-empty
(let [collection "docs"]
(is (empty? (mgcol/find-seq collection)))))
(deftest find-multiple-documents-when-collection-is-empty (deftest find-multiple-documents-when-collection-is-empty
(let [collection "libraries"] (let [collection "libraries"]
(is (empty? (mgcol/find collection { :language "Scala" }))))) (is (empty? (mgcol/find collection { :language "Scala" })))))
@ -267,7 +260,6 @@
{ :language "JavaScript", :name "sprout-core" }]) { :language "JavaScript", :name "sprout-core" }])
(is (= 2 (monger.core/count (mgcol/find collection { :language #"Java*" })))))) (is (= 2 (monger.core/count (mgcol/find collection { :language #"Java*" }))))))
(deftest find-multiple-documents (deftest find-multiple-documents
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{ :language "Clojure", :name "monger" } (mgcol/insert-batch collection [{ :language "Clojure", :name "monger" }
@ -278,6 +270,13 @@
(is (= 3 (.count (mgcol/find collection { :language "Clojure" })))) (is (= 3 (.count (mgcol/find collection { :language "Clojure" }))))
(is (empty? (mgcol/find collection { :language "Java" }))))) (is (empty? (mgcol/find collection { :language "Java" })))))
(deftest find-document-specify-fields
(let [collection "libraries"
_ (mgcol/insert collection { :language "Clojure", :name "monger" })
result (mgcol/find collection { :language "Clojure"} [:language])]
(is (= (seq [:_id :language]) (keys (mgcnv/from-db-object (.next result) true))))))
(deftest find-and-iterate-over-multiple-documents-the-hard-way (deftest find-and-iterate-over-multiple-documents-the-hard-way
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{ :language "Clojure", :name "monger" } (mgcol/insert-batch collection [{ :language "Clojure", :name "monger" }
@ -523,3 +522,27 @@
(mgcol/insert-batch collection batch) (mgcol/insert-batch collection batch)
(is (= ["CA" "IL" "NY"] (sort (mgcol/distinct collection :state)))) (is (= ["CA" "IL" "NY"] (sort (mgcol/distinct collection :state))))
(is (= ["CA" "NY"] (sort (mgcol/distinct collection :state { :price { $gt 100.00 } })))))) (is (= ["CA" "NY"] (sort (mgcol/distinct collection :state { :price { $gt 100.00 } }))))))
;;
;; any?, empty?
;;
(deftest any-on-empty-collection
(let [collection "things"]
(is (not (mgcol/any? collection)))))
(deftest any-on-non-empty-collection
(let [collection "things"
_ (mgcol/insert collection { :language "Clojure", :name "langohr" })]
(is (mgcol/any? "things"))
(is (mgcol/any? "things" {:language "Clojure"}))))
(deftest empty-on-empty-collection
(let [collection "things"]
(is (mgcol/empty? collection))))
(deftest empty-on-non-empty-collection
(let [collection "things"
_ (mgcol/insert collection { :language "Clojure", :name "langohr" })]
(is (not (mgcol/empty? "things")))))