Merge pull request #78 from michaelklishin/explicit-db-argument

Finishes #76
This commit is contained in:
Michael Klishin 2014-05-12 08:20:29 +04:00
commit da2effbfc9
50 changed files with 2614 additions and 4568 deletions

View file

@ -1,6 +1,62 @@
## Changes between 1.8.0 and 2.0.0 ## Changes between 1.8.0 and 2.0.0
No changes yet. `2.0` is a major release that has **breaking public API changes**.
### Explicit Connection/DB/GridFS Argument
In Monger 2.0, all key public API functions require an explicit
DB/connection/GridFS object to be provided instead of relying on
a shared dynamic var. This makes Monger much easier to use with
systems such as Component and Jig, as well as concurrent
applications that need to work with multiple connections, database,
or GridFS filesystems.
In other words, instead of
``` clojure
(require '[monger.collection :as mc])
(mc/insert "libraries" {:name "Monger"})
```
it is now necessary to do
``` clojure
(require '[monger.collection :as mc])
(mc/insert db "libraries" {:name "Monger"})
```
This also means that `monger.core/connect!` and
`monger.core/connect-via-uri!` were removed, as was
`monger.multi` namespaces.
To connect to MongoDB, use `monger.core/connect`:
``` clojure
(require '[monger.core :as mg])
(let [conn (mg/connect)])
```
or `monger.core/connect-via-uri`:
``` clojure
(require '[monger.core :as mg])
(let [{:keys [conn db]} (mg/connect-via-uri "mongodb://clojurewerkz/monger:monger@127.0.0.1/monger-test4")])
```
To get a database reference, use `monger.core/get-db`, which now requires a connection
object:
``` clojure
(require '[monger.core :as mg])
(let [conn (mg/connect)
db (mg/get-db conn "monger-test")])
```
## Changes between 1.8.0-beta2 and 1.8.0 ## Changes between 1.8.0-beta2 and 1.8.0

View file

@ -40,9 +40,9 @@
[cheshire "5.3.1" :exclusions [org.clojure/clojure]] [cheshire "5.3.1" :exclusions [org.clojure/clojure]]
[org.clojure/tools.cli "0.3.1" :exclusions [org.clojure/clojure]] [org.clojure/tools.cli "0.3.1" :exclusions [org.clojure/clojure]]
[org.clojure/core.cache "0.6.3" :exclusions [org.clojure/clojure]] [org.clojure/core.cache "0.6.3" :exclusions [org.clojure/clojure]]
[ring/ring-core "1.2.1"] [ring/ring-core "1.2.1" :exclusions [org.clojure/clojure]]
[com.novemberain/validateur "2.1.0"] [com.novemberain/validateur "2.1.0" :exclusions [org.clojure/clojure]]
[ragtime/ragtime.core "0.3.4"]] [ragtime/ragtime.core "0.3.4" :exclusions [org.clojure/clojure]]]
:plugins [[codox "0.6.6"]] :plugins [[codox "0.6.6"]]
:codox {:sources ["src/clojure"] :codox {:sources ["src/clojure"]
:output-dir "doc/api" :output-dir "doc/api"

View file

@ -11,7 +11,7 @@
"clojure.core.cache implementation(s) on top of MongoDB. "clojure.core.cache implementation(s) on top of MongoDB.
Related documentation guide: http://clojuremongodb.info/articles/integration.html" Related documentation guide: http://clojuremongodb.info/articles/integration.html"
(:require [monger.collection :as mc] (:require [monger.collection :as mc :refer [find-one find-by-id find-map-by-id]]
[clojure.core.cache :as cache] [clojure.core.cache :as cache]
[monger.conversion :as cnv]) [monger.conversion :as cnv])
(:import clojure.core.cache.CacheProtocol (:import clojure.core.cache.CacheProtocol
@ -25,87 +25,37 @@
(def ^{:const true} (def ^{:const true}
default-cache-collection "cache_entries") default-cache-collection "cache_entries")
(defn- ^DBObject find-one
[^DB db ^String collection ^Map ref]
(.findOne (.getCollection db (name collection))
(cnv/to-db-object ref)))
(defn- find-by-id
"A version of monger.collection/find-by-id that does not require the
fields argument"
[^DB db ^String collection id]
(find-one db collection {:_id id}))
(defn- find-map-by-id
"A version of monger.collection/find-by-map-id that accepts database
as an argument"
[^DB db ^String collection id]
(cnv/from-db-object ^DBObject (find-one db collection {:_id id}) true))
;; ;;
;; API ;; API
;; ;;
(defrecord BasicMongerCache [collection]) (defrecord BasicMongerCache [db collection])
(extend-protocol cache/CacheProtocol (extend-protocol cache/CacheProtocol
BasicMongerCache BasicMongerCache
(lookup [c k] (lookup [c k]
(let [m (mc/find-map-by-id (:collection c) k)] (let [m (mc/find-map-by-id (:db c) (:collection c) k)]
(:value m))) (:value m)))
(has? [c k] (has? [c k]
(not (nil? (mc/find-by-id (get c :collection) k)))) (not (nil? (mc/find-by-id (:db c) (:collection c) k))))
(hit [this k] (hit [this k]
this) this)
(miss [c k v] (miss [c k v]
(mc/insert (get c :collection) {:_id k :value v}) (mc/insert (:db c) (:collection c) {:_id k :value v})
c)
(evict [c k]
(mc/remove-by-id (get c :collection) k)
c)
(seed [c m]
(mc/insert-batch (get c :collection) (map (fn [[k v]]
{:_id k :value v}) m))
c))
(defn basic-monger-cache-factory
([]
(BasicMongerCache. default-cache-collection))
([collection]
(BasicMongerCache. collection))
([collection base]
(cache/seed (BasicMongerCache. collection) base)))
(defrecord DatabaseAwareMongerCache [db collection])
(extend-protocol cache/CacheProtocol
DatabaseAwareMongerCache
(lookup [c k]
(let [m (find-map-by-id (:db c) (:collection c) k)]
(:value m)))
(has? [c k]
(not (nil? (find-by-id (:db c) (:collection c) k))))
(hit [this k]
this)
(miss [c k v]
(mc/insert (:db c) (:collection c) {:_id k :value v} WriteConcern/SAFE)
c) c)
(evict [c k] (evict [c k]
(mc/remove-by-id (:db c) (:collection c) k) (mc/remove-by-id (:db c) (:collection c) k)
c) c)
(seed [c m] (seed [c m]
(mc/insert-batch (:db c) (:collection c) (map (fn [[k v]] (mc/insert-batch (:db c) (:collection c) (map (fn [[k v]]
{:_id k :value v}) m) WriteConcern/SAFE) {:_id k :value v}) m))
c)) c))
(defn db-aware-monger-cache-factory (defn basic-monger-cache-factory
([db] ([^DB db]
(DatabaseAwareMongerCache. db default-cache-collection)) (BasicMongerCache. db default-cache-collection))
([db collection] ([^DB db collection]
(DatabaseAwareMongerCache. db collection)) (BasicMongerCache. db collection))
([db collection base] ([^DB db collection base]
(cache/seed (DatabaseAwareMongerCache. db collection) base))) (cache/seed (BasicMongerCache. db collection) base)))

View file

@ -46,26 +46,22 @@
(defn ^WriteResult insert (defn ^WriteResult insert
"Saves @document@ to @collection@ and returns write result monger.result/ok? and similar functions operate on. 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 In case you need the exact inserted document returned, with the :_id key generated,
instead. use monger.collection/insert-and-return instead.
EXAMPLES: EXAMPLES:
;; returns write result ;; returns write result
(monger.collection/insert \"people\" {:name \"Joe\", :age 30}) (monger.collection/insert db \"people\" {:name \"Joe\", :age 30})
(monger.collection/insert \"people\" {:name \"Joe\", :age 30, WriteConcern/SAFE}) (monger.collection/insert db \"people\" {:name \"Joe\", :age 30, WriteConcern/SAFE})
" "
([^String collection document] ([^DB db ^String coll document]
(.insert (.getCollection monger.core/*mongodb-database* (name collection)) (.insert (.getCollection db (name coll))
(to-db-object document) (to-db-object document)
^WriteConcern monger.core/*mongodb-write-concern*)) ^WriteConcern monger.core/*mongodb-write-concern*))
([^String collection document ^WriteConcern concern] ([^DB db ^String coll document ^WriteConcern concern]
(.insert (.getCollection monger.core/*mongodb-database* (name collection)) (.insert (.getCollection db (name coll))
(to-db-object document)
concern))
([^DB db ^String collection document ^WriteConcern concern]
(.insert (.getCollection db (name collection))
(to-db-object document) (to-db-object document)
concern))) concern)))
@ -78,21 +74,19 @@
EXAMPLES: EXAMPLES:
;; returns the entire document with :_id generated ;; returns the entire document with :_id generated
(monger.collection/insert-and-return \"people\" {:name \"Joe\", :age 30}) (monger.collection/insert-and-return db \"people\" {:name \"Joe\", :age 30})
(monger.collection/insert-and-return \"people\" {:name \"Joe\", :age 30, WriteConcern/SAFE}) (monger.collection/insert-and-return db \"people\" {:name \"Joe\", :age 30, WriteConcern/SAFE})
" "
([^String collection document] ([^DB db ^String coll document]
(insert-and-return ^DB monger.core/*mongodb-database* collection document ^WriteConcern monger.core/*mongodb-write-concern*)) (insert-and-return db coll document ^WriteConcern monger.core/*mongodb-write-concern*))
([^String collection document ^WriteConcern concern] ([^DB db ^String coll 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 ;; 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 ;; 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 ;; from the Clojure map we are passing in. Plus, this approach is very awkward with immutable data
;; structures being the default. MK. ;; structures being the default. MK.
(let [doc (merge {:_id (ObjectId.)} document)] (let [doc (merge {:_id (ObjectId.)} document)]
(insert db collection doc concern) (insert db coll doc concern)
doc))) doc)))
@ -101,21 +95,17 @@
EXAMPLES: EXAMPLES:
(monger.collection/insert-batch \"people\" [{:name \"Joe\", :age 30}, {:name \"Paul\", :age 27}]) (monger.collection/insert-batch db \"people\" [{:name \"Joe\", :age 30}, {:name \"Paul\", :age 27}])
(monger.collection/insert-batch \"people\" [{:name \"Joe\", :age 30}, {:name \"Paul\", :age 27}] WriteConcern/NORMAL) (monger.collection/insert-batch db \"people\" [{:name \"Joe\", :age 30}, {:name \"Paul\", :age 27}] WriteConcern/NORMAL)
" "
([^String collection ^List documents] ([^DB db ^String coll ^List documents]
(.insert (.getCollection monger.core/*mongodb-database* (name collection)) (.insert (.getCollection db (name coll))
^List (to-db-object documents) ^List (to-db-object documents)
^WriteConcern monger.core/*mongodb-write-concern*)) ^WriteConcern monger.core/*mongodb-write-concern*))
([^String collection ^List documents ^WriteConcern concern] ([^DB db ^String coll ^List documents ^WriteConcern concern]
(.insert (.getCollection monger.core/*mongodb-database* (name collection)) (.insert (.getCollection db (name coll))
^List (to-db-object documents)
concern))
([^DB db ^String collection ^List documents ^WriteConcern concern]
(.insert (.getCollection db (name collection))
^List (to-db-object documents) ^List (to-db-object documents)
concern))) concern)))
@ -130,25 +120,21 @@
EXAMPLES: EXAMPLES:
;; return all objects in this collection. ;; return all objects in this collection.
(mgcol/find \"people\") (mgcol/find db \"people\")
;; return all objects matching query ;; return all objects matching query
(mgcol/find \"people\" {:company \"Comp Corp\"}) (mgcol/find db \"people\" {:company \"Comp Corp\"})
;; return all objects matching query, taking only specified fields ;; return all objects matching query, taking only specified fields
(mgcol/find \"people\" {:company \"Comp Corp\"} [:first_name :last_name]) (mgcol/find db \"people\" {:company \"Comp Corp\"} [:first_name :last_name])
" "
([^String collection] ([^DB db ^String coll]
(.find (.getCollection monger.core/*mongodb-database* (name collection)))) (.find (.getCollection db (name coll))))
([^String collection ^Map ref] ([^DB db ^String coll ^Map ref]
(.find (.getCollection monger.core/*mongodb-database* (name collection)) (.find (.getCollection db (name coll))
(to-db-object ref))) (to-db-object ref)))
([^String collection ^Map ref fields] ([^DB db ^String coll ^Map ref fields]
(.find (.getCollection monger.core/*mongodb-database* (name collection)) (.find (.getCollection db (name coll))
(to-db-object ref)
(as-field-selector fields)))
([^DB db ^String collection ^Map ref fields]
(.find (.getCollection db (name collection))
(to-db-object ref) (to-db-object ref)
(as-field-selector fields)))) (as-field-selector fields))))
@ -157,32 +143,26 @@
This function returns clojure Seq of Maps. This function returns clojure Seq of Maps.
If you want to work directly with DBObject, use find. If you want to work directly with DBObject, use find.
" "
([^String collection] ([^DB db ^String coll]
(with-open [dbc (find collection)] (with-open [dbc (find db coll)]
(map (fn [x] (from-db-object x true)) dbc))) (map (fn [x] (from-db-object x true)) dbc)))
([^String collection ^Map ref] ([^DB db ^String coll ^Map ref]
(with-open [dbc (find collection ref)] (with-open [dbc (find db coll ref)]
(map (fn [x] (from-db-object x true)) dbc))) (map (fn [x] (from-db-object x true)) dbc)))
([^String collection ^Map ref fields] ([^DB db ^String coll ^Map ref fields]
(with-open [dbc (find collection ref fields)] (with-open [dbc (find db coll ref fields)]
(map (fn [x] (from-db-object x true)) dbc)))
([^DB db ^String collection ^Map ref fields]
(with-open [dbc (find db collection ref fields)]
(map (fn [x] (from-db-object x true)) dbc)))) (map (fn [x] (from-db-object x true)) dbc))))
(defn find-seq (defn find-seq
"Queries for objects in this collection, returns ISeq of DBObjects." "Queries for objects in this collection, returns ISeq of DBObjects."
([^String collection] ([^DB db ^String coll]
(with-open [dbc (find collection)] (with-open [dbc (find db coll)]
(seq dbc))) (seq dbc)))
([^String collection ^Map ref] ([^DB db ^String coll ^Map ref]
(with-open [dbc (find collection ref)] (with-open [dbc (find db coll ref)]
(seq dbc))) (seq dbc)))
([^String collection ^Map ref fields] ([^DB db ^String coll ^Map ref fields]
(with-open [dbc (find collection ref fields)] (with-open [dbc (find db coll ref fields)]
(seq dbc)))
([^DB db ^String collection ^Map ref fields]
(with-open [dbc (find db collection ref fields)]
(seq dbc)))) (seq dbc))))
;; ;;
@ -194,33 +174,29 @@
EXAMPLES: EXAMPLES:
(mgcol/find-one collection {:language \"Clojure\"}) (mgcol/find-one db collection {:language \"Clojure\"})
;; Return only :language field. ;; Return only :language field.
;; Note that _id field is always returned. ;; Note that _id field is always returned.
(mgcol/find-one collection {:language \"Clojure\"} [:language]) (mgcol/find-one db collection {:language \"Clojure\"} [:language])
" "
([^String collection ^Map ref] ([^DB db ^String coll ^Map ref]
(.findOne (.getCollection monger.core/*mongodb-database* (name collection)) (.findOne (.getCollection db (name coll))
(to-db-object ref))) (to-db-object ref)))
([^String collection ^Map ref fields] ([^DB db ^String coll ^Map ref fields]
(.findOne (.getCollection monger.core/*mongodb-database* (name collection)) (.findOne (.getCollection db (name coll))
(to-db-object ref)
^DBObject (as-field-selector fields)))
([^DB db ^String collection ^Map ref fields]
(.findOne (.getCollection db (name collection))
(to-db-object ref) (to-db-object ref)
^DBObject (as-field-selector fields)))) ^DBObject (as-field-selector 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." "Returns a single object converted to Map from this collection matching the query."
([^String collection ^Map ref] ([^DB db ^String coll ^Map ref]
(from-db-object ^DBObject (find-one collection ref) true)) (from-db-object ^DBObject (find-one db coll ref) true))
([^String collection ^Map ref fields] ([^DB db ^String coll ^Map ref fields]
(from-db-object ^DBObject (find-one collection ref fields) true)) (from-db-object ^DBObject (find-one db coll ref fields) true))
([^String collection ^Map ref fields keywordize] ([^DB db ^String coll ^Map ref fields keywordize]
(from-db-object ^DBObject (find-one collection ref fields) keywordize))) (from-db-object ^DBObject (find-one db coll ref fields) keywordize)))
;; ;;
@ -233,27 +209,32 @@
EXAMPLES: EXAMPLES:
;; Find and modify a document ;; Find and modify a document
(mgcol/find-and-modify collection {:language \"Python\"} {:language \"Clojure\"}) (mgcol/find-and-modify db collection {:language \"Python\"} {:language \"Clojure\"})
;; If multiple documents match, choose the first one in the specified order ;; If multiple documents match, choose the first one in the specified order
(mgcol/find-and-modify collection {:language \"Python\"} {:language \"Clojure\"} :sort {:language -1}) (mgcol/find-and-modify db collection {:language \"Python\"} {:language \"Clojure\"} {:sort {:language -1}})
;; Remove the object before returning ;; Remove the object before returning
(mgcol/find-and-modify collection {:language \"Python\"} {} :remove true) (mgcol/find-and-modify db collection {:language \"Python\"} {} {:remove true})
;; Return the modified object instead of the old one ;; Return the modified object instead of the old one
(mgcol/find-and-modify collection {:language \"Python\"} {:language \"Clojure\"} :return-new true) (mgcol/find-and-modify db collection {:language \"Python\"} {:language \"Clojure\"} {:return-new true})
;; Retrieve a subset of fields ;; Retrieve a subset of fields
(mgcol/find-and-modify collection {:language \"Python\"} {:language \"Clojure\"} :fields [ :language ]) (mgcol/find-and-modify db collection {:language \"Python\"} {:language \"Clojure\"} {:fields [ :language ]})
;; Create the object if it doesn't exist ;; Create the object if it doesn't exist
(mgcol/find-and-modify collection {:language \"Factor\"} {:language \"Clojure\"} :upsert true) (mgcol/find-and-modify db collection {:language \"Factor\"} {:language \"Clojure\"} {:upsert true})
" "
([^String collection ^Map conditions ^Map document & {:keys [fields sort remove return-new upsert keywordize] :or ([^DB db ^String coll ^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
(let [coll (.getCollection monger.core/*mongodb-database* (name collection)) sort nil
remove false
return-new false
upsert false
keywordize true}}]
(let [coll (.getCollection db (name coll))
maybe-fields (when fields (as-field-selector fields)) maybe-fields (when fields (as-field-selector fields))
maybe-sort (when sort (to-db-object sort))] maybe-sort (when sort (to-db-object sort))]
(from-db-object (from-db-object
@ -275,54 +256,41 @@
;; Note that _id field is always returned. ;; Note that _id field is always returned.
(mgcol/find-one-by-id collection (ObjectId. \"4ef45ab4744e9fd632640e2d\") [:language]) (mgcol/find-one-by-id collection (ObjectId. \"4ef45ab4744e9fd632640e2d\") [:language])
" "
([^String collection id] ([^DB db ^String coll id]
(check-not-nil! id "id must not be nil") (check-not-nil! id "id must not be nil")
(find-one collection {:_id id})) (find-one db coll {:_id id}))
([^String collection id fields] ([^DB db ^String coll id fields]
(check-not-nil! id "id must not be nil") (check-not-nil! id "id must not be nil")
(find-one collection {:_id id} fields)) (find-one db coll {:_id id} fields)))
([^DB db ^String collection id fields]
(check-not-nil! id "id must not be nil")
(find-one db 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." "Returns a single object, converted to map with matching _id field."
([^String collection id] ([^DB db ^String coll id]
(check-not-nil! id "id must not be nil") (check-not-nil! id "id must not be nil")
(from-db-object ^DBObject (find-one-as-map collection {:_id id}) true)) (from-db-object ^DBObject (find-one-as-map db coll {:_id id}) true))
([^String collection id fields] ([^DB db ^String coll id fields]
(check-not-nil! id "id must not be nil") (check-not-nil! id "id must not be nil")
(from-db-object ^DBObject (find-one-as-map collection {:_id id} fields) true)) (from-db-object ^DBObject (find-one-as-map db coll {:_id id} fields) true))
([^String collection id fields keywordize] ([^DB db ^String coll id fields keywordize]
(check-not-nil! id "id must not be nil") (check-not-nil! id "id must not be nil")
(from-db-object ^DBObject (find-one-as-map collection {:_id id} fields) keywordize))) (from-db-object ^DBObject (find-one-as-map db coll {:_id id} fields) keywordize)))
;;
;; monger.collection/group
;;
;; TBD
;; ;;
;; monger.collection/count ;; monger.collection/count
;; ;;
(defn count (defn count
"Returns the number of documents in this collection. "Returns the number of documents in this collection.
Takes optional conditions as an argument. Takes optional conditions as an argument.
(monger.collection/count collection) (monger.collection/count db coll)
(monger.collection/count collection {:first_name \"Paul\"})" (monger.collection/count db coll {:first_name \"Paul\"})"
(^long [^String collection] (^long [^DB db ^String coll]
(.count (.getCollection monger.core/*mongodb-database* (name collection)))) (.count (.getCollection db (name coll))))
(^long [^String collection ^Map conditions] (^long [^DB db ^String coll ^Map conditions]
(.count (.getCollection monger.core/*mongodb-database* (name collection)) (to-db-object conditions))) (.count (.getCollection db (name coll)) (to-db-object conditions))))
(^long [^DB db ^String collection ^Map conditions]
(.count (.getCollection db (name collection)) (to-db-object conditions))))
(defn any? (defn any?
"Whether the collection has any items at all, or items matching query. "Whether the collection has any items at all, or items matching query.
@ -330,28 +298,24 @@
EXAMPLES: EXAMPLES:
;; whether the collection has any items ;; whether the collection has any items
(mgcol/any? collection) (mgcol/any? db coll)
(mgcol/any? collection {:language \"Clojure\"})) (mgcol/any? db coll {:language \"Clojure\"}))
" "
([^String collection] ([^DB db ^String coll]
(> (count collection) 0)) (> (count db coll) 0))
([^String collection ^Map conditions] ([^DB db ^String coll ^Map conditions]
(> (count collection conditions) 0)) (> (count db coll conditions) 0)))
([^DB db ^String collection ^Map conditions]
(> (count db collection conditions) 0)))
(defn empty? (defn empty?
"Whether the collection is empty. "Whether the collection is empty.
EXAMPLES: EXAMPLES:
(mgcol/empty? \"things\") (mgcol/empty? db \"things\")
" "
([^String collection] [^DB db ^String coll]
(= (count collection) 0)) (= (count db coll {}) 0))
([^DB db ^String collection]
(= (count db collection {}) 0)))
;; monger.collection/update ;; monger.collection/update
@ -364,17 +328,17 @@
EXAMPLES EXAMPLES
(monger.collection/update \"people\" {:first_name \"Raul\"} {\"$set\" {:first_name \"Paul\"}}) (monger.collection/update db \"people\" {:first_name \"Raul\"} {\"$set\" {:first_name \"Paul\"}})
You can use all the Mongodb Modifier Operations ($inc, $set, $unset, $push, $pushAll, $addToSet, $pop, $pull You can use all the Mongodb Modifier Operations ($inc, $set, $unset, $push, $pushAll, $addToSet, $pop, $pull
$pullAll, $rename, $bit) here, as well $pullAll, $rename, $bit) here, as well
EXAMPLES EXAMPLES
(monger.collection/update \"people\" {:first_name \"Paul\"} {\"$set\" {:index 1}}) (monger.collection/update db \"people\" {:first_name \"Paul\"} {\"$set\" {:index 1}})
(monger.collection/update \"people\" {:first_name \"Paul\"} {\"$inc\" {:index 5}}) (monger.collection/update db \"people\" {:first_name \"Paul\"} {\"$inc\" {:index 5}})
(monger.collection/update \"people\" {:first_name \"Paul\"} {\"$unset\" {:years_on_stage 1}}) (monger.collection/update db \"people\" {:first_name \"Paul\"} {\"$unset\" {:years_on_stage 1}})
It also takes modifiers, such as :upsert and :multi. It also takes modifiers, such as :upsert and :multi.
@ -382,16 +346,19 @@
;; add :band field to all the records found in \"people\" collection, otherwise only the first matched record ;; add :band field to all the records found in \"people\" collection, otherwise only the first matched record
;; will be updated ;; will be updated
(monger.collection/update \"people\" {} {\"$set\" {:band \"The Beatles\"}} :multi true) (monger.collection/update db \"people\" {} {\"$set\" {:band \"The Beatles\"}} :multi true)
;; inserts the record if it did not exist in the collection ;; inserts the record if it did not exist in the collection
(monger.collection/update \"people\" {:first_name \"Yoko\"} {:first_name \"Yoko\" :last_name \"Ono\"} :upsert true) (monger.collection/update db \"people\" {:first_name \"Yoko\"} {:first_name \"Yoko\" :last_name \"Ono\"} {:upsert true)
By default :upsert and :multi are false." By default :upsert and :multi are false."
([^String collection ^Map conditions ^Map document & {:keys [upsert multi write-concern] :or {upsert false ([^DB db ^String coll ^Map conditions ^Map document]
(update db coll conditions document {}))
([^DB db ^String coll ^Map conditions ^Map document {:keys [upsert multi write-concern]
:or {upsert false
multi false multi false
write-concern monger.core/*mongodb-write-concern*}}] write-concern monger.core/*mongodb-write-concern*}}]
(.update (.getCollection monger.core/*mongodb-database* (name collection)) (.update (.getCollection db (name coll))
(to-db-object conditions) (to-db-object conditions)
(to-db-object document) (to-db-object document)
upsert upsert
@ -405,21 +372,27 @@
sets :upsert to true. sets :upsert to true.
See monger.collection/update documentation" See monger.collection/update documentation"
[^String collection ^Map conditions ^Map document & {:keys [multi write-concern] :or {multi false ([^DB db ^String coll ^Map conditions ^Map document]
(upsert db coll conditions document {}))
([^DB db ^String coll ^Map conditions ^Map document {:keys [multi write-concern]
:or {multi false
write-concern monger.core/*mongodb-write-concern*}}] write-concern monger.core/*mongodb-write-concern*}}]
(update collection conditions document :multi multi :write-concern write-concern :upsert true)) (update db coll conditions document {:multi multi :write-concern write-concern :upsert true})))
(defn ^WriteResult update-by-id (defn ^WriteResult update-by-id
"Update a document with given id" "Update a document with given id"
[^String collection id ^Map document & {:keys [upsert write-concern] :or {upsert false ([^DB db ^String coll id ^Map document]
(update-by-id db coll id document {}))
([^DB db ^String coll id ^Map document {:keys [upsert write-concern]
:or {upsert false
write-concern monger.core/*mongodb-write-concern*}}] write-concern monger.core/*mongodb-write-concern*}}]
(check-not-nil! id "id must not be nil") (check-not-nil! id "id must not be nil")
(.update (.getCollection monger.core/*mongodb-database* (name collection)) (.update (.getCollection db (name coll))
(to-db-object {:_id id}) (to-db-object {:_id id})
(to-db-object document) (to-db-object document)
upsert upsert
false false
write-concern)) write-concern)))
;; monger.collection/save ;; monger.collection/save
@ -435,18 +408,14 @@
EXAMPLES EXAMPLES
(monger.collection/save \"people\" {:first_name \"Ian\" :last_name \"Gillan\"}) (monger.collection/save db \"people\" {:first_name \"Ian\" :last_name \"Gillan\"})
" "
([^String collection ^Map document] ([^DB db ^String coll ^Map document]
(.save (.getCollection monger.core/*mongodb-database* (name collection)) (.save (.getCollection db (name coll))
(to-db-object document) (to-db-object document)
monger.core/*mongodb-write-concern*)) monger.core/*mongodb-write-concern*))
([^String collection ^Map document ^WriteConcern write-concern] ([^DB db ^String coll ^Map document ^WriteConcern write-concern]
(.save (.getCollection monger.core/*mongodb-database* (name collection)) (.save (.getCollection db (name coll))
(to-db-object document)
write-concern))
([^DB db ^String collection ^Map document ^WriteConcern write-concern]
(.save (.getCollection db (name collection))
(to-db-object document) (to-db-object document)
write-concern))) write-concern)))
@ -465,15 +434,13 @@
(monger.collection/save-and-return \"people\" {:first_name \"Ian\" :last_name \"Gillan\"}) (monger.collection/save-and-return \"people\" {:first_name \"Ian\" :last_name \"Gillan\"})
" "
([^String collection ^Map document] ([^DB db ^String coll ^Map document]
(save-and-return ^DB monger.core/*mongodb-database* collection document ^WriteConcern monger.core/*mongodb-write-concern*)) (save-and-return db coll document ^WriteConcern monger.core/*mongodb-write-concern*))
([^String collection ^Map document ^WriteConcern write-concern] ([^DB db ^String coll ^Map document ^WriteConcern write-concern]
(save-and-return ^DB monger.core/*mongodb-database* collection document write-concern))
([^DB db ^String collection ^Map document ^WriteConcern write-concern]
;; see the comment in insert-and-return. Here we additionally need to make sure to not scrap the :_id key if ;; see the comment in insert-and-return. Here we additionally need to make sure to not scrap the :_id key if
;; it is already present. MK. ;; it is already present. MK.
(let [doc (merge {:_id (ObjectId.)} document)] (let [doc (merge {:_id (ObjectId.)} document)]
(save db collection doc write-concern) (save db coll doc write-concern)
doc))) doc)))
@ -484,28 +451,30 @@
EXAMPLES EXAMPLES
(monger.collection/remove collection) ;; Removes all documents from DB (monger.collection/remove db collection) ;; Removes all documents from DB
(monger.collection/remove collection {:language \"Clojure\"}) ;; Removes documents based on given query (monger.collection/remove db collection {:language \"Clojure\"}) ;; Removes documents based on given query
" "
([^String collection] ([^DB db ^String coll]
(.remove (.getCollection monger.core/*mongodb-database* (name collection)) (to-db-object {}))) (.remove (.getCollection db (name coll)) (to-db-object {})))
([^String collection ^Map conditions] ([^DB db ^String coll ^Map conditions]
(.remove (.getCollection monger.core/*mongodb-database* (name collection)) (to-db-object conditions))) (.remove (.getCollection db (name coll)) (to-db-object conditions))))
([^DB db ^String collection ^Map conditions]
(.remove (.getCollection db (name collection)) (to-db-object conditions))))
(defn ^WriteResult remove-by-id (defn ^WriteResult remove-by-id
"Removes a single document with given id" "Removes a single document with given id"
([^String collection id] [^DB db ^String coll id]
(remove-by-id monger.core/*mongodb-database* collection id))
([^DB db ^String collection id]
(check-not-nil! id "id must not be nil") (check-not-nil! id "id must not be nil")
(let [coll (.getCollection db (name collection))] (let [coll (.getCollection db (name coll))]
(.remove coll (to-db-object {:_id id}))))) (.remove coll (to-db-object {:_id id}))))
(defn purge-many
"Purges (removes all documents from) multiple collections. Intended
to be used in test environments."
[^DB db xs]
(doseq [coll xs]
(remove db coll)))
;; ;;
;; monger.collection/create-index ;; monger.collection/create-index
@ -517,18 +486,14 @@
EXAMPLES EXAMPLES
;; Will create an index on the \"language\" field ;; Will create an index on the \"language\" field
(monger.collection/create-index collection {\"language\" 1}) (monger.collection/create-index db collection {\"language\" 1})
(monger.collection/create-index collection {\"language\" 1} {:unique true :name \"unique_language\"}) (monger.collection/create-index db collection {\"language\" 1} {:unique true :name \"unique_language\"})
" "
([^String collection ^Map keys] ([^DB db ^String coll ^Map keys]
(.createIndex (.getCollection monger.core/*mongodb-database* (name collection)) (as-field-selector keys))) (.createIndex (.getCollection db (name coll)) (as-field-selector keys)))
([^String collection ^Map keys options] ([^DB db ^String coll ^Map keys ^Map options]
(.createIndex (.getCollection monger.core/*mongodb-database* (name collection)) (.createIndex (.getCollection db (name coll))
(as-field-selector keys)
(to-db-object options)))
([^DB db ^String collection ^Map keys ^Map options]
(.createIndex (.getCollection db (name collection))
(as-field-selector keys) (as-field-selector keys)
(to-db-object options)))) (to-db-object options))))
@ -550,18 +515,18 @@
;; create a regular index ;; create a regular index
;; clojure.core/array-map produces an ordered map ;; clojure.core/array-map produces an ordered map
(monger.collection/ensure-index \"documents\" (array-map \"language\" 1)) (monger.collection/ensure-index db \"documents\" (array-map \"language\" 1))
;; create a unique index ;; create a unique index
(monger.collection/ensure-index \"pages\" (array-map :url 1) {:unique true}) (monger.collection/ensure-index db \"pages\" (array-map :url 1) {:unique true})
" "
([^String collection ^Map keys] ([^DB db ^String coll ^Map keys]
(.ensureIndex (.getCollection monger.core/*mongodb-database* (name collection)) (as-field-selector keys))) (.ensureIndex (.getCollection db (name coll)) (as-field-selector keys)))
([^String collection ^Map keys ^Map options] ([^DB db ^String coll ^Map keys ^Map options]
(.ensureIndex (.getCollection monger.core/*mongodb-database* (name collection)) (.ensureIndex (.getCollection db (name coll))
(as-field-selector keys) (as-field-selector keys)
(to-db-object options))) (to-db-object options)))
([^String collection ^Map keys ^String name ^Boolean unique?] ([^DB db ^String coll ^Map keys ^String name unique?]
(.ensureIndex (.getCollection monger.core/*mongodb-database* (name collection)) (.ensureIndex (.getCollection db (name coll))
(as-field-selector keys) (as-field-selector keys)
name name
unique?))) unique?)))
@ -579,8 +544,8 @@
(monger.collection/indexes-on collection) (monger.collection/indexes-on collection)
" "
[^String collection] [^DB db ^String coll]
(from-db-object (.getIndexInfo (.getCollection monger.core/*mongodb-database* (name collection))) true)) (from-db-object (.getIndexInfo (.getCollection db (name coll))) true))
;; ;;
@ -589,17 +554,13 @@
(defn drop-index (defn drop-index
"Drops an index from this collection." "Drops an index from this collection."
([^String collection ^String idx-name] [^DB db ^String coll ^String idx-name]
(.dropIndex (.getCollection monger.core/*mongodb-database* (name collection)) idx-name)) (.dropIndex (.getCollection db (name coll)) idx-name))
([^DB db ^String collection ^String idx-name]
(.dropIndex (.getCollection db (name collection)) idx-name)))
(defn drop-indexes (defn drop-indexes
"Drops all indixes from this collection." "Drops all indixes from this collection."
([^String collection] [^DB db ^String coll]
(.dropIndexes (.getCollection monger.core/*mongodb-database* (name collection)))) (.dropIndexes (.getCollection db (name coll))))
([^DB db ^String collection]
(.dropIndexes (.getCollection db (name collection)))))
;; ;;
@ -612,12 +573,10 @@
EXAMPLE: EXAMPLE:
(monger.collection/exists? \"coll\") (monger.collection/exists? db \"coll\")
" "
([^String collection] ([^DB db ^String coll]
(.collectionExists monger.core/*mongodb-database* collection)) (.collectionExists db coll)))
([^DB db ^String collection]
(.collectionExists db collection)))
(defn create (defn create
"Creates a collection with a given name and options. "Creates a collection with a given name and options.
@ -631,12 +590,10 @@
EXAMPLE: EXAMPLE:
;; create a capped collection ;; create a capped collection
(monger.collection/create \"coll\" {:capped true :size 100000 :max 10}) (monger.collection/create db \"coll\" {:capped true :size 100000 :max 10})
" "
([^String collection ^Map options] [^DB db ^String coll ^Map options]
(.createCollection monger.core/*mongodb-database* collection (to-db-object options))) (.createCollection db coll (to-db-object options)))
([^DB db ^String collection ^Map options]
(.createCollection db collection (to-db-object options))))
(defn drop (defn drop
"Deletes collection from database. "Deletes collection from database.
@ -645,24 +602,20 @@
(monger.collection/drop \"collection-to-drop\") (monger.collection/drop \"collection-to-drop\")
" "
([^String collection] [^DB db ^String coll]
(.drop (.getCollection monger.core/*mongodb-database* (name collection)))) (.drop (.getCollection db (name coll))))
([^DB db ^String collection]
(.drop (.getCollection db (name collection)))))
(defn rename (defn rename
"Renames collection. "Renames collection.
EXAMPLE: EXAMPLE:
(monger.collection/rename \"old_name\" \"new_name\") (monger.collection/rename db \"old_name\" \"new_name\")
" "
([^String from, ^String to] ([^DB db ^String from, ^String to]
(.rename (.getCollection monger.core/*mongodb-database* from) to)) (.rename (.getCollection db from) to))
([^String from ^String to ^Boolean drop-target] ([^DB db ^String from ^String to drop-target?]
(.rename (.getCollection monger.core/*mongodb-database* from) to drop-target)) (.rename (.getCollection db from) to drop-target?)))
([^DB db ^String from ^String to ^Boolean drop-target]
(.rename (.getCollection db from) to drop-target)))
;; ;;
;; Map/Reduce ;; Map/Reduce
@ -670,11 +623,11 @@
(defn map-reduce (defn map-reduce
"Performs a map reduce operation" "Performs a map reduce operation"
([^String collection ^String js-mapper ^String js-reducer ^String output ^Map query] ([^DB db ^String coll ^String js-mapper ^String js-reducer ^String output ^Map query]
(let [coll (.getCollection monger.core/*mongodb-database* (name collection))] (let [coll (.getCollection db (name coll))]
(.mapReduce coll js-mapper js-reducer output (to-db-object query)))) (.mapReduce coll js-mapper js-reducer output (to-db-object query))))
([^String collection ^String js-mapper ^String js-reducer ^String output ^MapReduceCommand$OutputType output-type ^Map query] ([^DB db ^String coll ^String js-mapper ^String js-reducer ^String output ^MapReduceCommand$OutputType output-type ^Map query]
(let [coll (.getCollection monger.core/*mongodb-database* (name collection))] (let [coll (.getCollection db (name coll))]
(.mapReduce coll js-mapper js-reducer output output-type (to-db-object query))))) (.mapReduce coll js-mapper js-reducer output output-type (to-db-object query)))))
@ -684,12 +637,10 @@
(defn distinct (defn distinct
"Finds distinct values for a key" "Finds distinct values for a key"
([^String collection ^String key] ([^DB db ^String coll ^String key]
(.distinct (.getCollection monger.core/*mongodb-database* (name collection)) ^String (to-db-object key))) (.distinct (.getCollection db (name coll)) ^String (to-db-object key)))
([^String collection ^String key ^Map query] ([^DB db ^String coll ^String key ^Map query]
(.distinct (.getCollection monger.core/*mongodb-database* (name collection)) ^String (to-db-object key) (to-db-object query))) (.distinct (.getCollection db (name coll)) ^String (to-db-object key) (to-db-object query))))
([^DB db ^String collection ^String key ^Map query]
(.distinct (.getCollection db (name collection)) ^String (to-db-object key) (to-db-object query))))
;; ;;
@ -697,12 +648,12 @@
;; ;;
(defn aggregate (defn aggregate
"Performs aggregation query. MongoDB 2.1/2.2+ only. "Executes an aggregation query. MongoDB 2.2+ only.
See http://docs.mongodb.org/manual/applications/aggregation/ to learn more." See http://docs.mongodb.org/manual/applications/aggregation/ to learn more."
[^String collection stages] [^DB db ^String coll stages]
(let [res (monger.core/command {:aggregate collection :pipeline stages})] (let [res (monger.core/command db {:aggregate coll :pipeline stages})]
;; this is what DBCollection#distinct does. Turning a blind eye! ;; this is what DBCollection#distinct does. Turning a blind's eye!
(.throwOnError res) (.throwOnError res)
(map #(from-db-object % true) (.get res "result")))) (map #(from-db-object % true) (.get res "result"))))
@ -717,5 +668,5 @@
(defn system-collection? (defn system-collection?
"Evaluates to true if the given collection name refers to a system collection. System collections "Evaluates to true if the given collection name refers to a system collection. System collections
are prefixed with system. or fs. (default GridFS collection prefix)" are prefixed with system. or fs. (default GridFS collection prefix)"
[^String collection] [^String coll]
(re-find system-collection-pattern collection)) (re-find system-collection-pattern coll))

View file

@ -20,7 +20,7 @@
* http://clojuremongodb.info/articles/mapreduce.html" * http://clojuremongodb.info/articles/mapreduce.html"
(:require monger.core (:require monger.core
[monger.conversion :refer :all]) [monger.conversion :refer :all])
(:import [com.mongodb DB DBObject])) (:import [com.mongodb MongoClient DB DBObject]))
;; ;;
@ -29,77 +29,59 @@
(defn admin-command (defn admin-command
"Executes a command on the admin database" "Executes a command on the admin database"
[m] [^MongoClient conn m]
(monger.core/command (monger.core/admin-db) m)) (monger.core/command (monger.core/admin-db conn) m))
(defn raw-admin-command (defn raw-admin-command
"Executes a command on the admin database" "Executes a command on the admin database"
[^DBObject cmd] [^MongoClient conn ^DBObject cmd]
(monger.core/raw-command (monger.core/admin-db) cmd)) (monger.core/raw-command (monger.core/admin-db conn) cmd))
(defn collection-stats (defn collection-stats
([collection] [^DB database collection]
(collection-stats monger.core/*mongodb-database* collection)) (monger.core/command database {:collstats collection}))
([^DB database collection]
(monger.core/command database {:collstats collection})))
(defn db-stats (defn db-stats
([] [^DB database]
(db-stats monger.core/*mongodb-database*)) (monger.core/command database {:dbStats 1}))
([^DB database]
(monger.core/command database {:dbStats 1})))
(defn reindex-collection (defn reindex-collection
"Forces an existing collection to be reindexed using the reindexCollection command" "Forces an existing collection to be reindexed using the reindexCollection command"
([^String collection] [^DB database ^String collection]
(reindex-collection monger.core/*mongodb-database* collection)) (monger.core/command database {:reIndex collection}))
([^DB database ^String collection]
(monger.core/command database {:reIndex collection})))
(defn rename-collection (defn rename-collection
"Changes the name of an existing collection using the renameCollection command" "Changes the name of an existing collection using the renameCollection command"
([^String from ^String to] [^DB db ^String from ^String to]
(reindex-collection monger.core/*mongodb-database* from to)) (monger.core/command db (sorted-map :renameCollection from :to to)))
([^DB database ^String from ^String to]
(monger.core/command database (sorted-map :renameCollection from :to to))))
(defn convert-to-capped (defn convert-to-capped
"Converts an existing, non-capped collection to a capped collection using the convertToCapped command" "Converts an existing, non-capped collection to a capped collection using the convertToCapped command"
([^String collection ^long size] [^DB db ^String collection ^long size]
(convert-to-capped monger.core/*mongodb-database* collection size)) (monger.core/command db (sorted-map :convertToCapped collection :size size)))
([^DB database ^String collection ^long size]
(monger.core/command database (sorted-map :convertToCapped collection :size size))))
(defn empty-capped (defn empty-capped
"Removes all documents from a capped collection using the emptycapped command" "Removes all documents from a capped collection using the emptycapped command"
([^String collection] [^DB db ^String collection]
(empty-capped monger.core/*mongodb-database* collection)) (monger.core/command db {:emptycapped collection}))
([^DB database ^String collection]
(monger.core/command database {:emptycapped collection})))
(defn compact (defn compact
"Rewrites and defragments a single collection using the compact command. This also forces all indexes on the collection to be rebuilt" "Rewrites and defragments a single collection using the compact command. This also forces all indexes on the collection to be rebuilt"
([^String collection] [^DB db ^String collection]
(compact monger.core/*mongodb-database* collection)) (monger.core/command db {:compact collection}))
([^DB database ^String collection]
(monger.core/command database {:compact collection})))
(defn server-status (defn server-status
([] [^DB db]
(server-status monger.core/*mongodb-database*)) (monger.core/command db {:serverStatus 1}))
([^DB database]
(monger.core/command database {:serverStatus 1})))
(defn top (defn top
[] [^MongoClient conn]
(monger.core/command (monger.core/get-db "admin") {:top 1})) (monger.core/command (monger.core/admin-db conn) {:top 1}))
(defn search (defn search
([^String collection query] [^DB db ^String collection query]
(monger.core/command {"text" collection "search" query})) (monger.core/command db {"text" collection "search" query}))
([^DB database ^String collection query]
(monger.core/command database {"text" collection "search" query})))

View file

@ -31,28 +31,24 @@
(def ^:dynamic ^String *mongodb-host* "127.0.0.1") (def ^:dynamic ^String *mongodb-host* "127.0.0.1")
(def ^:dynamic ^long *mongodb-port* 27017) (def ^:dynamic ^long *mongodb-port* 27017)
(declare ^:dynamic ^MongoClient *mongodb-connection*)
(declare ^:dynamic ^DB *mongodb-database*)
(def ^:dynamic ^WriteConcern *mongodb-write-concern* WriteConcern/ACKNOWLEDGED) (def ^:dynamic ^WriteConcern *mongodb-write-concern* WriteConcern/ACKNOWLEDGED)
(declare ^:dynamic ^GridFS *mongodb-gridfs*)
;; ;;
;; API ;; API
;; ;;
(defn ^com.mongodb.MongoClient connect (defn ^MongoClient connect
"Connects to MongoDB. When used without arguments, connects to "Connects to MongoDB. When used without arguments, connects to
Arguments: Arguments:
:host (*mongodb-host* by default) :host (\"127.0.0.1\" by default)
:port (*mongodb-port* by default) :port (27017 by default)
EXAMPLES EXAMPLES
(monger.core/connect) (monger.core/connect)
(monger.core/connect { :host \"db3.intranet.local\", :port 27787 }) (monger.core/connect {:host \"db3.intranet.local\" :port 27787})
;; Connecting to a replica set with a couple of seeds ;; Connecting to a replica set with a couple of seeds
(let [^MongoClientOptions opts (mg/mongo-options :threads-allowed-to-block-for-connection-multiplier 300) (let [^MongoClientOptions opts (mg/mongo-options :threads-allowed-to-block-for-connection-multiplier 300)
@ -79,55 +75,32 @@
(defn get-db-names (defn get-db-names
"Gets a list of all database names present on the server" "Gets a list of all database names present on the server"
([] [^MongoClient conn]
(get-db-names *mongodb-connection*)) (set (.getDatabaseNames conn)))
([^MongoClient connection]
(set (.getDatabaseNames connection))))
(defn ^com.mongodb.DB get-db (defn ^DB get-db
"Get database reference by name. "Get database reference by name.
EXAMPLES EXAMPLES
(monger.core/get-db \"myapp_production\")
(monger.core/get-db connection \"myapp_production\")" (monger.core/get-db connection \"myapp_production\")"
([] [^MongoClient conn ^String name]
*mongodb-database*) (.getDB conn name))
([^String name]
(.getDB *mongodb-connection* name))
([^MongoClient connection ^String name]
(.getDB connection name)))
(defn ^com.mongodb.DB current-db
"Returns currently used database"
[]
*mongodb-database*)
(defn drop-db (defn drop-db
"Drops a database" "Drops a database"
([^String db] [^MongoClient conn ^String db]
(.dropDatabase *mongodb-connection* db)) (.dropDatabase conn db))
([^MongoClient conn ^String db]
(.dropDatabase conn db)))
(defn ^GridFS get-gridfs
"Get GridFS for the given database.
(defmacro with-connection EXAMPLES
[conn & body]
`(binding [*mongodb-connection* ~conn]
(do ~@body)))
(defmacro with-db
[db & body]
`(binding [*mongodb-database* ~db]
(do ~@body)))
(defmacro with-gridfs
[fs & body]
`(binding [*mongodb-gridfs* ~fs]
(do ~@body)))
(monger.core/get-gridfs connection \"myapp_production\")"
[^MongoClient conn ^String name]
(GridFS. (.getDB conn name)))
(defn server-address (defn server-address
([^String hostname] ([^String hostname]
@ -135,7 +108,6 @@
([^String hostname ^Long port] ([^String hostname ^Long port]
(ServerAddress. hostname port))) (ServerAddress. hostname port)))
(defn mongo-options (defn mongo-options
[& { :keys [connections-per-host threads-allowed-to-block-for-connection-multiplier [& { :keys [connections-per-host threads-allowed-to-block-for-connection-multiplier
max-wait-time connect-timeout socket-timeout socket-keep-alive auto-connect-retry max-auto-connect-retry-time max-wait-time connect-timeout socket-timeout socket-keep-alive auto-connect-retry max-auto-connect-retry-time
@ -165,57 +137,27 @@
(.cursorFinalizerEnabled mob cursor-finalizer-enabled)) (.cursorFinalizerEnabled mob cursor-finalizer-enabled))
(.build mob))) (.build mob)))
(defn disconnect
(defn set-connection!
"Sets given MongoDB connection as default by altering *mongodb-connection* var"
^MongoClient [^MongoClient conn]
(alter-var-root (var *mongodb-connection*) (constantly conn)))
(defn connect!
"Connect to MongoDB, store connection in the *mongodb-connection* var"
^MongoClient [& args]
(let [c (apply connect args)]
(set-connection! c)))
(defn disconnect!
"Closes default connection to MongoDB" "Closes default connection to MongoDB"
[] [^MongoClient conn]
(.close *mongodb-connection*)) (.close conn))
(defn set-db!
"Sets *mongodb-database* var to given db, updates *mongodb-gridfs* var state. Recommended to be used for
applications that only use one database."
[db]
(alter-var-root (var *mongodb-database*) (constantly db))
(alter-var-root (var *mongodb-gridfs*) (constantly (GridFS. db))))
(def ^{:doc "Combines set-db! and get-db, so (use-db \"mydb\") is the same as (set-db! (get-db \"mydb\"))"}
use-db! (comp set-db! get-db))
(def ^:const admin-db-name "admin") (def ^:const admin-db-name "admin")
(defn ^DB admin-db (defn ^DB admin-db
"Returns admin database" "Returns admin database"
[] [^MongoClient conn]
(get-db admin-db-name)) (get-db conn admin-db-name))
(defn set-default-write-concern! (defn set-default-write-concern!
[wc] [wc]
"Set *mongodb-write-concert* var to :wc "Sets *mongodb-write-concert*"
Unlike the official Java driver, Monger uses WriteConcern/SAFE by default. We think defaults should be safe first
and WebScale fast second."
(alter-var-root #'*mongodb-write-concern* (constantly wc))) (alter-var-root #'*mongodb-write-concern* (constantly wc)))
(defn authenticate (defn authenticate
([^String username ^chars password]
(authenticate *mongodb-connection* *mongodb-database* username password))
([^DB db ^String username ^chars password] ([^DB db ^String username ^chars password]
(authenticate *mongodb-connection* db username password))
([^MongoClient connection ^DB db ^String username ^chars password]
(try (try
(.authenticate db username password) (.authenticate db username password)
;; MongoDB Java driver's exception hierarchy is a little crazy ;; MongoDB Java driver's exception hierarchy is a little crazy
@ -234,41 +176,25 @@
user (.getUsername uri) user (.getUsername uri)
pwd (.getPassword uri)] pwd (.getPassword uri)]
(when (and user pwd) (when (and user pwd)
(when-not (authenticate conn db user pwd) (when-not (authenticate db user pwd)
(throw (IllegalArgumentException. (format "Could not authenticate with MongoDB. Either database name or credentials are invalid. Database name: %s, username: %s" (.getName db) user))))) (throw (IllegalArgumentException. (format "Could not authenticate with MongoDB. Either database name or credentials are invalid. Database name: %s, username: %s" (.getName db) user)))))
{:conn conn, :db db})) {:conn conn :db db}))
(defn connect-via-uri!
"Connects to MongoDB using a URI, sets up default connection and database. Commonly used for PaaS-based applications,
for example, running on Heroku. If username and password are provided, performs authentication."
[uri-string]
(let [{:keys [conn db]} (connect-via-uri uri-string)]
(set-connection! conn)
(when db
(set-db! db))
conn))
(defn ^com.mongodb.CommandResult command (defn ^com.mongodb.CommandResult command
"Runs a database command (please check MongoDB documentation for the complete list of commands). "Runs a database command (please check MongoDB documentation for the complete list of commands).
Ordering of keys in the command document may matter. Please use sorted maps instead of map literals, for example: Ordering of keys in the command document may matter. Please use sorted maps instead of map literals, for example:
(sorted-map geoNear \"bars\" :near 50 :test 430 :num 10) (sorted-map geoNear db \"bars\" :near 50 :test 430 :num 10)
For commonly used commands (distinct, count, map/reduce, etc), use monger.command and monger.collection functions such as For commonly used commands (distinct, count, map/reduce, etc), use monger.command and monger.collection functions such as
/distinct, /count, /drop, /dropIndexes, and /mapReduce respectively." /distinct, /count, /drop, /dropIndexes, and /mapReduce respectively."
([^Map cmd] [^DB database ^Map cmd]
(.command ^DB *mongodb-database* ^DBObject (to-db-object cmd))) (.command ^DB database ^DBObject (to-db-object cmd)))
([^DB database ^Map cmd]
(.command ^DB database ^DBObject (to-db-object cmd))))
(defn ^com.mongodb.CommandResult raw-command (defn ^com.mongodb.CommandResult raw-command
"Like monger.core/command but accepts DBObjects" "Like monger.core/command but accepts DBObjects"
([^DBObject cmd] [^DB database ^DBObject cmd]
(.command ^DB *mongodb-database* cmd)) (.command database cmd))
([^DB database ^DBObject cmd]
(.command database cmd)))
(defprotocol Countable (defprotocol Countable
(count [this] "Returns size of the object")) (count [this] "Returns size of the object"))
@ -295,8 +221,6 @@
Important note: when calling this method directly, it is undefined which connection \"getLastError\" is called on. Important note: when calling this method directly, it is undefined which connection \"getLastError\" is called on.
You may need to explicitly use a \"consistent Request\", see requestStart() For most purposes it is better not to call this method directly but instead use WriteConcern." You may need to explicitly use a \"consistent Request\", see requestStart() For most purposes it is better not to call this method directly but instead use WriteConcern."
([]
(get-last-error *mongodb-database*))
([^DB database] ([^DB database]
(.getLastError ^DB database)) (.getLastError ^DB database))
([^DB database ^Integer w ^Integer wtimeout ^Boolean fsync] ([^DB database ^Integer w ^Integer wtimeout ^Boolean fsync]

View file

@ -11,7 +11,7 @@
"Helper-functions for dbCursor object: "Helper-functions for dbCursor object:
* to initialize new cursor, * to initialize new cursor,
* for CRUD functionality of options of dbCursor" * for CRUD functionality of options of dbCursor"
(:import [com.mongodb DBCursor Bytes] (:import [com.mongodb DB DBCursor Bytes]
[java.util List Map] [java.util List Map]
[java.lang Integer] [java.lang Integer]
[clojure.lang Keyword]) [clojure.lang Keyword])
@ -20,13 +20,13 @@
(defn ^DBCursor make-db-cursor (defn ^DBCursor make-db-cursor
"initializes new db-cursor." "initializes new db-cursor."
([^String collection] ([^DB db ^String coll]
(make-db-cursor collection {} {})) (make-db-cursor db coll {} {}))
([^String collection ^Map ref] ([^DB db ^String coll ^Map ref]
(make-db-cursor collection ref {})) (make-db-cursor db coll ref {}))
([^String collection ^Map ref fields] ([^DB db ^String coll ^Map ref fields]
(.find (.find
(.getCollection monger.core/*mongodb-database* (name collection)) (.getCollection db (name coll))
(to-db-object ref) (to-db-object ref)
(as-field-selector fields)))) (as-field-selector fields))))

View file

@ -16,25 +16,22 @@
[monger.conversion :refer :all])) [monger.conversion :refer :all]))
;;
;; API
;;
(defn add-user (defn add-user
"Adds a new user for this db" "Adds a new user for this db"
([^String username, ^chars password] [^DB db ^String username ^chars password]
(.addUser ^DB monger.core/*mongodb-database* username password)) (.addUser db username password))
([^DB database ^String username ^chars password]
(.addUser ^DB database username password)))
(defn drop-db (defn drop-db
"Drops the currently set database (via core/set-db) or the specified database." "Drops the currently set database (via core/set-db) or the specified database."
([] [^DB db]
(.dropDatabase ^DB monger.core/*mongodb-database*)) (.dropDatabase db))
([^DB database]
(.dropDatabase ^DB database)))
(defn get-collection-names (defn get-collection-names
"Returns a set containing the names of all collections in this database." "Returns a set containing the names of all collections in this database."
([] ([^DB db]
(set (.getCollectionNames ^DB monger.core/*mongodb-database*))) (set (.getCollectionNames db))))
([^DB database]
(set (.getCollectionNames ^DB database))))

View file

@ -18,8 +18,9 @@
[monger.conversion :refer :all] [monger.conversion :refer :all]
[clojurewerkz.support.fn :refer [fpartial]]) [clojurewerkz.support.fn :refer [fpartial]])
(:import [com.mongodb DB DBObject] (:import [com.mongodb DB DBObject]
org.bson.types.ObjectId
[com.mongodb.gridfs GridFS GridFSInputFile] [com.mongodb.gridfs GridFS GridFSInputFile]
[java.io InputStream File])) [java.io InputStream ByteArrayInputStream File]))
;; ;;
;; Implementation ;; Implementation
@ -41,24 +42,16 @@
(defn remove (defn remove
([] [^GridFS fs query]
(remove {})) (.remove fs ^DBObject (to-db-object query)))
([query]
(.remove ^GridFS monger.core/*mongodb-gridfs* ^DBObject (to-db-object query)))
([^GridFS fs query]
(.remove fs ^DBObject (to-db-object query))))
(defn remove-all (defn remove-all
([] [^GridFS fs]
(remove {})) (remove fs {}))
([^GridFS fs]
(remove fs {})))
(defn all-files (defn all-files
([] ([^GridFS fs]
(.getFileList ^GridFS monger.core/*mongodb-gridfs*)) (.getFileList fs (to-db-object {})))
([query]
(.getFileList ^GridFS monger.core/*mongodb-gridfs* query))
([^GridFS fs query] ([^GridFS fs query]
(.getFileList fs query))) (.getFileList fs query)))
@ -66,10 +59,8 @@
(fpartial from-db-object true)) (fpartial from-db-object true))
(defn files-as-maps (defn files-as-maps
([] ([^GridFS fs]
(map converter (all-files))) (files-as-maps fs {}))
([query]
(map converter (all-files (to-db-object query))))
([^GridFS fs query] ([^GridFS fs query]
(map converter (all-files fs (to-db-object query))))) (map converter (all-files fs (to-db-object query)))))
@ -78,27 +69,30 @@
;; Plumbing (low-level API) ;; Plumbing (low-level API)
;; ;;
(defprotocol GridFSInputFileFactory (defprotocol InputStreamFactory
(^com.mongodb.gridfs.GridFSInputFile make-input-file [input] "Makes GridFSInputFile out of the given input")) (^InputStream to-input-stream [input] "Makes InputStream out of the given input"))
(extend byte-array-type (extend byte-array-type
GridFSInputFileFactory InputStreamFactory
{:make-input-file (fn [^bytes input] {:to-input-stream (fn [^bytes input]
(.createFile ^GridFS monger.core/*mongodb-gridfs* input))}) (ByteArrayInputStream. input))})
(extend-protocol GridFSInputFileFactory (extend-protocol InputStreamFactory
String String
(make-input-file [^String input] (to-input-stream [^String input]
(.createFile ^GridFS monger.core/*mongodb-gridfs* ^InputStream (io/make-input-stream input {:encoding "UTF-8"}))) (io/make-input-stream input {:encoding "UTF-8"}))
File File
(make-input-file [^File input] (to-input-stream [^File input]
(.createFile ^GridFS monger.core/*mongodb-gridfs* ^InputStream (io/make-input-stream input {:encoding "UTF-8"}))) (io/make-input-stream input {:encoding "UTF-8"}))
InputStream InputStream
(make-input-file [^InputStream input] (to-input-stream [^InputStream input]
(.createFile ^GridFS monger.core/*mongodb-gridfs* ^InputStream input))) input))
(defn ^GridFSInputFile make-input-file
[^GridFS fs input]
(.createFile fs (to-input-stream input)))
(defmacro store (defmacro store
[^GridFSInputFile input & body] [^GridFSInputFile input & body]
@ -106,9 +100,8 @@
(.save f# GridFS/DEFAULT_CHUNKSIZE) (.save f# GridFS/DEFAULT_CHUNKSIZE)
(from-db-object f# true))) (from-db-object f# true)))
;; ;;
;; "New" DSL, a higher-level API ;; Higher-level API
;; ;;
(defn save (defn save
@ -141,48 +134,34 @@
;; Finders ;; Finders
;; ;;
(defprotocol Finders (defn find
(find [input] "Finds multiple files using given input (an ObjectId, filename or query)") [^GridFS fs query]
(find-one [input] "Finds one file using given input (an ObjectId, filename or query)") (.find fs (to-db-object query)))
(find-maps [input] "Finds multiple files using given input (an ObjectId, filename or query), returning a Clojure map")
(find-one-as-map [input] "Finds one file using given input (an ObjectId, filename or query), returning a Clojure map"))
(extend-protocol Finders (defn find-by-filename
String [^GridFS fs ^String filename]
(find [^String input] (.find fs (to-db-object {"filename" filename})))
(.find ^GridFS monger.core/*mongodb-gridfs* input))
(find-one [^String input]
(.findOne ^GridFS monger.core/*mongodb-gridfs* input))
(find-maps [^String input]
(map converter (find input)))
(find-one-as-map [^String input]
(converter (find-one input)))
org.bson.types.ObjectId (defn find-by-md5
(find-one [^org.bson.types.ObjectId input] [^GridFS fs ^String md5]
(.findOne ^GridFS monger.core/*mongodb-gridfs* input)) (.find fs (to-db-object {"md5" md5})))
(find-one-as-map [^org.bson.types.ObjectId input]
(converter (find-one input)))
(defn find-one
[^GridFS fs query]
(.findOne fs (to-db-object query)))
DBObject (defn find-maps
(find [^DBObject input] [^GridFS fs query]
(.find ^GridFS monger.core/*mongodb-gridfs* input)) (map converter (find fs query)))
(find-one [^DBObject input]
(.findOne ^GridFS monger.core/*mongodb-gridfs* input))
(find-maps [^DBObject input]
(map converter (find input)))
(find-one-as-map [^DBObject input]
(converter (find-one input)))
;; using java.util.Map here results in (occasional) recursion (defn find-one-as-map
clojure.lang.IPersistentMap [^GridFS fs query]
(find [^java.util.Map input] (converter (find-one fs query)))
(find (to-db-object input)))
(find-one [^java.util.Map input]
(find-one (to-db-object input)))
(find-maps [^java.util.Map input]
(find-maps (to-db-object input)))
(find-one-as-map [^java.util.Map input]
(find-one-as-map (to-db-object input))))
(defn find-by-id
[^GridFS fs ^ObjectId id]
(.findOne fs id))
(defn find-map-by-id
[^GridFS fs ^ObjectId id]
(converter (find-one fs id)))

View file

@ -1,73 +0,0 @@
;; Copyright (c) 2011-2014 Michael S. Klishin
;;
;; The use and distribution terms for this software are covered by the
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file epl-v10.html at the root of this distribution.
;; By using this software in any fashion, you are agreeing to be bound by
;; the terms of this license.
;; You must not remove this notice, or any other, from this software.
(ns monger.internal.fn)
;;
;; Implementation
;;
(defn- apply-to-values [m f]
"Applies function f to all values in map m"
(into {} (for [[k v] m]
[k (f v)])))
;;
;; API
;;
(defn fpartial
"Like clojure.core/partial but prepopulates last N arguments (first is passed in later)"
[f & args]
(fn [arg & more] (apply f arg (concat args more))))
(defprotocol IFNExpansion
(expand-all [x] "Replaces functions with their invocation results, recursively expands maps, evaluates all other values to themselves")
(expand-all-with [x f] "Replaces functions with their invocation results that function f is applied to, recursively expands maps, evaluates all other values to themselves"))
(extend-protocol IFNExpansion
java.lang.Integer
(expand-all [i] i)
(expand-all-with [i f] i)
java.lang.Long
(expand-all [l] l)
(expand-all-with [l f] l)
java.lang.String
(expand-all [s] s)
(expand-all-with [s f] s)
java.lang.Float
(expand-all [fl] fl)
(expand-all-with [fl f] fl)
java.lang.Double
(expand-all [d] d)
(expand-all-with [d f] d)
;; maps are also functions, so be careful here. MK.
clojure.lang.IPersistentMap
(expand-all [m] (apply-to-values m expand-all))
(expand-all-with [m f] (apply-to-values m (fpartial expand-all-with f)))
clojure.lang.PersistentVector
(expand-all [v] (map expand-all v))
(expand-all-with [v f] (map (fpartial expand-all-with f) v))
;; this distinguishes functions from maps, sets and so on, which are also
;; clojure.lang.AFn subclasses. MK.
clojure.lang.AFunction
(expand-all [f] (f))
(expand-all-with [f expander] (expander f))
Object
(expand-all [x] x)
(expand-all-with [x f] x))

View file

@ -1,360 +0,0 @@
(ns monger.multi.collection
"Includes versions of key monger.collection functions that always take a database
as explicit argument instead of relying on monger.core/*mongodb-database*.
Use these functions when you need to work with multiple databases or manage database
and connection lifecycle explicitly."
(:refer-clojure :exclude [find remove count empty? distinct drop])
(: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)
(:require monger.core
monger.result
[monger.conversion :refer :all]
[monger.constraints :refer :all]))
;;
;; API
;;
(defn ^WriteResult insert
"Like monger.collection/insert but always takes a database as explicit argument"
([^DB db ^String collection document]
(.insert (.getCollection db (name collection))
(to-db-object document)
monger.core/*mongodb-write-concern*))
([^DB db ^String collection document ^WriteConcern concern]
(.insert (.getCollection db (name collection))
(to-db-object document)
concern)))
(defn ^clojure.lang.IPersistentMap insert-and-return
"Like monger.collection/insert-and-return but always takes a database as explicit argument"
([^DB db ^String collection document]
(let [doc (merge {:_id (ObjectId.)} document)]
(insert db collection doc monger.core/*mongodb-write-concern*)
doc))
([^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 {:_id (ObjectId.)} document)]
(insert db collection doc concern)
doc)))
(defn ^WriteResult insert-batch
"Like monger.collection/insert-batch but always takes a database as explicit argument"
([^DB db ^String collection ^List documents]
(.insert (.getCollection db (name collection))
^List (to-db-object documents)
monger.core/*mongodb-write-concern*))
([^DB db ^String collection ^List documents ^WriteConcern concern]
(.insert (.getCollection db (name collection))
^List (to-db-object documents)
concern)))
;;
;; monger.multi.collection/find
;;
(defn ^DBCursor find
"Like monger.collection/find but always takes a database as explicit argument"
([^DB db ^String collection]
(.find (.getCollection db (name collection))))
([^DB db ^String collection ^Map ref]
(.find (.getCollection db (name collection))
(to-db-object ref)))
([^DB db ^String collection ^Map ref fields]
(.find (.getCollection db (name collection))
(to-db-object ref)
(as-field-selector fields))))
(defn find-maps
"Like monger.collection/find-maps but always takes a database as explicit argument"
([^DB db ^String collection]
(with-open [dbc (find db collection)]
(map (fn [x] (from-db-object x true)) dbc)))
([^DB db ^String collection ^Map ref]
(with-open [dbc (find db collection ref)]
(map (fn [x] (from-db-object x true)) dbc)))
([^DB db ^String collection ^Map ref fields]
(with-open [dbc (find db collection ref fields)]
(map (fn [x] (from-db-object x true)) dbc))))
(defn find-seq
"Like monger.collection/find-seq but always takes a database as explicit argument"
([^DB db ^String collection]
(with-open [dbc (find db collection)]
(seq dbc)))
([^DB db ^String collection ^Map ref]
(with-open [dbc (find db collection ref)]
(seq dbc)))
([^DB db ^String collection ^Map ref fields]
(with-open [dbc (find db collection ref fields)]
(seq dbc))))
;;
;; monger.multi.collection/find-one
;;
(defn ^DBObject find-one
"Like monger.collection/find-one but always takes a database as explicit argument"
([^DB db ^String collection ^Map ref]
(.findOne (.getCollection db (name collection))
(to-db-object ref)))
([^DB db ^String collection ^Map ref fields]
(.findOne (.getCollection db (name collection))
(to-db-object ref)
^DBObject (as-field-selector fields))))
(defn ^IPersistentMap find-one-as-map
"Like monger.collection/find-one-as-map but always takes a database as explicit argument"
([^DB db ^String collection ^Map ref]
(from-db-object ^DBObject (find-one db collection ref) true))
([^DB db ^String collection ^Map ref fields]
(from-db-object ^DBObject (find-one db collection ref fields) true))
([^DB db ^String collection ^Map ref fields keywordize]
(from-db-object ^DBObject (find-one db collection ref fields) keywordize)))
;;
;; monger.multi.collection/find-and-modify
;;
(defn ^IPersistentMap find-and-modify
"Like monger.collection/find-and-modify but always takes a database as explicit argument"
([^DB db ^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 [coll (.getCollection db (name collection))
maybe-fields (when fields (as-field-selector fields))
maybe-sort (when sort (to-db-object sort))]
(from-db-object
^DBObject (.findAndModify ^DBCollection coll (to-db-object conditions) maybe-fields maybe-sort remove
(to-db-object document) return-new upsert) keywordize))))
;;
;; monger.multi.collection/find-by-id
;;
(defn ^DBObject find-by-id
"Like monger.collection/find-by-id but always takes a database as explicit argument"
([^DB db ^String collection id]
(check-not-nil! id "id must not be nil")
(find-one db collection {:_id id}))
([^DB db ^String collection id fields]
(check-not-nil! id "id must not be nil")
(find-one db collection {:_id id} fields)))
(defn ^IPersistentMap find-map-by-id
"Like monger.collection/find-map-by-id but always takes a database as explicit argument"
([^DB db ^String collection id]
(check-not-nil! id "id must not be nil")
(from-db-object ^DBObject (find-one-as-map db collection {:_id id}) true))
([^DB db ^String collection id fields]
(check-not-nil! id "id must not be nil")
(from-db-object ^DBObject (find-one-as-map db collection {:_id id} fields) true))
([^DB db ^String collection id fields keywordize]
(check-not-nil! id "id must not be nil")
(from-db-object ^DBObject (find-one-as-map db collection {:_id id} fields) keywordize)))
;;
;; monger.multi.collection/count
;;
(defn count
"Like monger.collection/count but always takes a database as explicit argument"
(^long [^DB db ^String collection]
(.count (.getCollection db (name collection)) (to-db-object {})))
(^long [^DB db ^String collection ^Map conditions]
(.count (.getCollection db (name collection)) (to-db-object conditions))))
(defn any?
"Like monger.collection/any? but always takes a database as explicit argument"
([^DB db ^String collection]
(> (count db collection) 0))
([^DB db ^String collection ^Map conditions]
(> (count db collection conditions) 0)))
(defn empty?
"Like monger.collection/empty? but always takes a database as explicit argument"
([^DB db ^String collection]
(= (count db collection {}) 0)))
(defn ^WriteResult update
"Like monger.collection/update but always takes a database as explicit argument"
([^DB db ^String collection ^Map conditions ^Map document & {:keys [upsert multi write-concern] :or {upsert false
multi false
write-concern monger.core/*mongodb-write-concern*}}]
(.update (.getCollection db (name collection))
(to-db-object conditions)
(to-db-object document)
upsert
multi
write-concern)))
(defn ^WriteResult upsert
"Like monger.collection/upsert but always takes a database as explicit argument"
[^DB db ^String collection ^Map conditions ^Map document & {:keys [multi write-concern] :or {multi false
write-concern monger.core/*mongodb-write-concern*}}]
(update db collection conditions document :multi multi :write-concern write-concern :upsert true))
(defn ^WriteResult update-by-id
"Like monger.collection/update-by-id but always takes a database as explicit argument"
[^DB db ^String collection id ^Map document & {:keys [upsert write-concern] :or {upsert false
write-concern monger.core/*mongodb-write-concern*}}]
(check-not-nil! id "id must not be nil")
(.update (.getCollection db (name collection))
(to-db-object {:_id id})
(to-db-object document)
upsert
false
write-concern))
(defn ^WriteResult save
"Like monger.collection/save but always takes a database as explicit argument"
([^DB db ^String collection ^Map document]
(.save (.getCollection db (name collection))
(to-db-object document)
monger.core/*mongodb-write-concern*))
([^DB db ^String collection ^Map document ^WriteConcern write-concern]
(.save (.getCollection db (name collection))
(to-db-object document)
write-concern)))
(defn ^clojure.lang.IPersistentMap save-and-return
"Like monger.collection/save-and-return but always takes a database as explicit argument"
([^DB db ^String collection ^Map document]
(save-and-return ^DB db collection document ^WriteConcern monger.core/*mongodb-write-concern*))
([^DB db ^String collection ^Map document ^WriteConcern write-concern]
;; see the comment in insert-and-return. Here we additionally need to make sure to not scrap the :_id key if
;; it is already present. MK.
(let [doc (merge {:_id (ObjectId.)} document)]
(save db collection doc write-concern)
doc)))
(defn ^WriteResult remove
"Like monger.collection/remove but always takes a database as explicit argument"
([^DB db ^String collection]
(.remove (.getCollection db (name collection)) (to-db-object {})))
([^DB db ^String collection ^Map conditions]
(.remove (.getCollection db (name collection)) (to-db-object conditions))))
(defn ^WriteResult remove-by-id
"Like monger.collection/remove-by-id but always takes a database as explicit argument"
([^DB db ^String collection id]
(check-not-nil! id "id must not be nil")
(let [coll (.getCollection db (name collection))]
(.remove coll (to-db-object {:_id id})))))
;;
;; monger.multi.collection/create-index
;;
(defn create-index
"Like monger.collection/create-index but always takes a database as explicit argument"
([^DB db ^String collection ^Map keys]
(.createIndex (.getCollection db (name collection)) (as-field-selector keys)))
([^DB db ^String collection ^Map keys ^Map options]
(.createIndex (.getCollection db (name collection))
(as-field-selector keys)
(to-db-object options))))
;;
;; monger.multi.collection/ensure-index
;;
(defn ensure-index
"Like monger.collection/ensure-index but always takes a database as explicit argument"
([^DB db ^String collection ^Map keys]
(.ensureIndex (.getCollection db (name collection)) (as-field-selector keys)))
([^DB db ^String collection ^Map keys ^Map options]
(.ensureIndex (.getCollection db (name collection))
(as-field-selector keys)
(to-db-object options)))
([^DB db ^String collection ^Map keys ^String name ^Boolean unique?]
(.ensureIndex (.getCollection db (name collection))
(as-field-selector keys)
name
unique?)))
;;
;; monger.multi.collection/indexes-on
;;
(defn indexes-on
"Like monger.collection/indexes-on but always takes a database as explicit argument"
[^DB db ^String collection]
(from-db-object (.getIndexInfo (.getCollection db (name collection))) true))
;;
;; monger.multi.collection/drop-index
;;
(defn drop-index
"Like monger.collection/drop-index but always takes a database as explicit argument"
([^DB db ^String collection ^String idx-name]
(.dropIndex (.getCollection db (name collection)) idx-name)))
(defn drop-indexes
"Like monger.collection/drop-indexes but always takes a database as explicit argument"
([^DB db ^String collection]
(.dropIndexes (.getCollection db (name collection)))))
;;
;; monger.multi.collection/exists?, /create, /drop, /rename
;;
(defn exists?
"Like monger.collection/exists? but always takes a database as explicit argument"
([^DB db ^String collection]
(.collectionExists db collection)))
(defn create
"Like monger.collection/create but always takes a database as explicit argument"
([^DB db ^String collection ^Map options]
(.createCollection db collection (to-db-object options))))
(defn drop
"Like monger.collection/drop but always takes a database as explicit argument"
([^DB db ^String collection]
(.drop (.getCollection db (name collection)))))
(defn rename
"Like monger.collection/rename but always takes a database as explicit argument"
([^DB db ^String from, ^String to]
(.rename (.getCollection db from) to))
([^DB db ^String from ^String to ^Boolean drop-target]
(.rename (.getCollection db from) to drop-target)))
;;
;; Map/Reduce
;;
(defn map-reduce
"Like monger.collection/map-reduce but always takes a database as explicit argument"
([^DB db ^String collection ^String js-mapper ^String js-reducer ^String output ^Map query]
(let [coll (.getCollection db (name collection))]
(.mapReduce coll js-mapper js-reducer output (to-db-object query))))
([^DB db ^String collection ^String js-mapper ^String js-reducer ^String output ^MapReduceCommand$OutputType output-type ^Map query]
(let [coll (.getCollection db (name collection))]
(.mapReduce coll js-mapper js-reducer output output-type (to-db-object query)))))
;;
;; monger.multi.collection/distinct
;;
(defn distinct
"Like monger.collection/distinct but always takes a database as explicit argument"
([^DB db ^String collection ^String key]
(.distinct (.getCollection db (name collection)) ^String (to-db-object key)))
([^DB db ^String collection ^String key ^Map query]
(.distinct (.getCollection db (name collection)) ^String (to-db-object key) (to-db-object query))))

View file

@ -63,7 +63,19 @@
(merge (empty-query) { :collection coll }))) (merge (empty-query) { :collection coll })))
(defn exec (defn exec
[{ :keys [^DBCollection collection query fields skip limit sort batch-size hint snapshot read-preference keywordize-fields options] :or { limit 0 batch-size 256 skip 0 } }] [{:keys [^DBCollection collection
query
fields
skip
limit
sort
batch-size
hint
snapshot
read-preference
keywordize-fields
options]
:or { limit 0 batch-size 256 skip 0 } }]
(with-open [cursor (doto (.find collection (to-db-object query) (as-field-selector fields)) (with-open [cursor (doto (.find collection (to-db-object query) (as-field-selector fields))
(.limit limit) (.limit limit)
(.skip skip) (.skip skip)
@ -132,10 +144,10 @@
(merge m { :limit per-page :skip (monger.internal.pagination/offset-for page per-page) })) (merge m { :limit per-page :skip (monger.internal.pagination/offset-for page per-page) }))
(defmacro with-collection (defmacro with-collection
[^String coll & body] [^DB db ^String coll & body]
`(let [coll# ~coll `(let [coll# ~coll
db-coll# (if (string? coll#) db-coll# (if (string? coll#)
(.getCollection ^DB monger.core/*mongodb-database* ^String coll#) (.getCollection ~db ^String coll#)
coll#) coll#)
query# (-> (empty-query db-coll#) ~@body)] query# (-> (empty-query db-coll#) ~@body)]
(exec query#))) (exec query#)))

View file

@ -22,7 +22,6 @@
migrations-collection "meta.migrations") migrations-collection "meta.migrations")
(extend-type com.mongodb.DB (extend-type com.mongodb.DB
ragtime/Migratable ragtime/Migratable
(add-migration-id [db id] (add-migration-id [db id]
@ -30,15 +29,13 @@
(remove-migration-id [db id] (remove-migration-id [db id]
(mc/remove-by-id db migrations-collection id)) (mc/remove-by-id db migrations-collection id))
(applied-migration-ids [db] (applied-migration-ids [db]
(mg/with-db db (let [xs (with-collection db migrations-collection
(let [xs (with-collection migrations-collection
(find {}) (find {})
(sort {:created_at 1}))] (sort {:created_at 1}))]
(vec (map :_id xs)))))) (vec (map :_id xs)))))
(defn flush-migrations! (defn flush-migrations!
"REMOVES all the information about previously performed migrations" "REMOVES all the information about previously performed migrations"
[db] [^DB db]
(mg/with-db db (mc/remove db migrations-collection))
(mc/remove migrations-collection)))

View file

@ -9,7 +9,7 @@
(ns monger.ring.session-store (ns monger.ring.session-store
(:require [ring.middleware.session.store :as ringstore] (:require [ring.middleware.session.store :as ringstore]
[monger.multi.collection :as mc] [monger.collection :as mc]
[monger.core :as mg] [monger.core :as mg]
[monger.conversion :refer :all]) [monger.conversion :refer :all])
(:import [java.util UUID Date] (:import [java.util UUID Date]
@ -78,12 +78,8 @@
(defn session-store (defn session-store
([] [^DB db ^String s]
(ClojureReaderBasedMongoDBSessionStore. mg/*mongodb-database* default-session-store-collection)) (ClojureReaderBasedMongoDBSessionStore. db s))
([^String s]
(ClojureReaderBasedMongoDBSessionStore. mg/*mongodb-database* s))
([^DB db ^String s]
(ClojureReaderBasedMongoDBSessionStore. db s)))
;; this session store won't store namespaced keywords correctly but stores results in a way ;; this session store won't store namespaced keywords correctly but stores results in a way
@ -111,9 +107,5 @@
(defn monger-store (defn monger-store
([] [^DB db ^String s]
(MongoDBSessionStore. mg/*mongodb-database* default-session-store-collection)) (MongoDBSessionStore. db s))
([^String s]
(MongoDBSessionStore. mg/*mongodb-database* s))
([^DB db ^String s]
(MongoDBSessionStore. db s)))

View file

@ -11,7 +11,7 @@
"Full text search queries support (MongoDB 2.4+)" "Full text search queries support (MongoDB 2.4+)"
(:require [monger.command :as cmd] (:require [monger.command :as cmd]
[monger.conversion :as cnv]) [monger.conversion :as cnv])
(:import [com.mongodb CommandResult BasicDBList DBObject])) (:import [com.mongodb DB CommandResult BasicDBList DBObject]))
;; ;;
;; Implementation ;; Implementation
@ -28,8 +28,8 @@
(defn search (defn search
"Performs a full text search query" "Performs a full text search query"
[^String collection query] [^DB db ^String collection query]
(cmd/search collection query)) (cmd/search db collection query))
(defn results-from (defn results-from
"Returns a lazy sequence of results from a search query response, sorted by score. "Returns a lazy sequence of results from a search query response, sorted by score.

View file

@ -1,44 +0,0 @@
;; Copyright (c) 2011-2014 Michael S. Klishin
;;
;; The use and distribution terms for this software are covered by the
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file epl-v10.html at the root of this distribution.
;; By using this software in any fashion, you are agreeing to be bound by
;; the terms of this license.
;; You must not remove this notice, or any other, from this software.
(ns monger.testkit
"Automated testing helpers"
(:require [monger.collection :as mc]))
;;
;; API
;;
(defmacro defcleaner
"Defines a fixture function that removes all documents from a collection. If collection is not specified,
a conventionally named var will be used. Supposed to be used with clojure.test/use-fixtures but may
be useful on its own.
Examples:
(defcleaner events) ;; collection name will be taken from the events-collection var
(defcleaner people \"accounts\") ;; collection name is given
"
([entities]
(let [coll-arg (symbol (str entities "-collection"))
fn-name (symbol (str "purge-" entities))]
`(defn ~fn-name
[f#]
(mc/remove ~coll-arg)
(f#)
(mc/remove ~coll-arg))))
([entities coll-name]
(let [coll-arg (name coll-name)
fn-name (symbol (str "purge-" entities))]
`(defn ~fn-name
[f#]
(mc/remove ~coll-arg)
(f#)
(mc/remove ~coll-arg)))))

View file

@ -1,18 +1,22 @@
(ns monger.test.aggregation-framework-test (ns monger.test.aggregation-framework-test
(:require monger.core [monger.collection :as mc] (:require [monger.core :as mg]
[monger.test.helper :as helper] [monger.collection :as mc]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]))
[monger.test.fixtures :refer :all]))
(let [conn (mg/connect)
db (mg/get-db conn "monger-test")
coll "docs"]
(defn purge-collections
[f]
(mc/purge-many db [coll])
(f)
(mc/purge-many db [coll]))
(helper/connect!) (use-fixtures :each purge-collections)
(use-fixtures :each purge-docs) (deftest test-basic-single-stage-$project-aggregation
(let [batch [{ :state "CA" :quantity 1 :price 199.00 }
(deftest test-basic-single-stage-$project-aggregation
(let [collection "docs"
batch [{ :state "CA" :quantity 1 :price 199.00 }
{ :state "NY" :quantity 2 :price 199.00 } { :state "NY" :quantity 2 :price 199.00 }
{ :state "NY" :quantity 1 :price 299.00 } { :state "NY" :quantity 1 :price 299.00 }
{ :state "IL" :quantity 2 :price 11.50 } { :state "IL" :quantity 2 :price 11.50 }
@ -24,16 +28,15 @@
{:quantity 2 :state "IL"} {:quantity 2 :state "IL"}
{:quantity 2 :state "CA"} {:quantity 2 :state "CA"}
{:quantity 3 :state "IL"}}] {:quantity 3 :state "IL"}}]
(mc/insert-batch collection batch) (mc/insert-batch db coll batch)
(is (= 6 (mc/count collection))) (is (= 6 (mc/count db coll)))
(let [result (set (map #(select-keys % [:state :quantity]) (let [result (set (map #(select-keys % [:state :quantity])
(mc/aggregate "docs" [{$project {:state 1 :quantity 1}}])))] (mc/aggregate db coll [{$project {:state 1 :quantity 1}}])))]
(is (= expected result))))) (is (= expected result)))))
(deftest test-basic-projection-with-multiplication (deftest test-basic-projection-with-multiplication
(let [collection "docs" (let [batch [{ :state "CA" :quantity 1 :price 199.00 }
batch [{ :state "CA" :quantity 1 :price 199.00 }
{ :state "NY" :quantity 2 :price 199.00 } { :state "NY" :quantity 2 :price 199.00 }
{ :state "NY" :quantity 1 :price 299.00 } { :state "NY" :quantity 1 :price 299.00 }
{ :state "IL" :quantity 2 :price 11.50 } { :state "IL" :quantity 2 :price 11.50 }
@ -45,23 +48,22 @@
{:_id "CA" :subtotal 5.9} {:_id "CA" :subtotal 5.9}
{:_id "IL" :subtotal 16.5} {:_id "IL" :subtotal 16.5}
{:_id "CA" :subtotal 199.0}}] {:_id "CA" :subtotal 199.0}}]
(mc/insert-batch collection batch) (mc/insert-batch db coll batch)
(let [result (set (mc/aggregate "docs" [{$project {:subtotal {$multiply ["$quantity", "$price"]} (let [result (set (mc/aggregate db coll [{$project {:subtotal {$multiply ["$quantity", "$price"]}
:_id "$state"}}]))] :_id "$state"}}]))]
(is (= expected result))))) (is (= expected result)))))
(deftest test-basic-total-aggregation (deftest test-basic-total-aggregation
(let [collection "docs" (let [batch [{ :state "CA" :quantity 1 :price 199.00 }
batch [{ :state "CA" :quantity 1 :price 199.00 }
{ :state "NY" :quantity 2 :price 199.00 } { :state "NY" :quantity 2 :price 199.00 }
{ :state "NY" :quantity 1 :price 299.00 } { :state "NY" :quantity 1 :price 299.00 }
{ :state "IL" :quantity 2 :price 11.50 } { :state "IL" :quantity 2 :price 11.50 }
{ :state "CA" :quantity 2 :price 2.95 } { :state "CA" :quantity 2 :price 2.95 }
{ :state "IL" :quantity 3 :price 5.50 }] { :state "IL" :quantity 3 :price 5.50 }]
expected #{{:_id "CA" :total 204.9} {:_id "IL" :total 39.5} {:_id "NY" :total 697.0}}] expected #{{:_id "CA" :total 204.9} {:_id "IL" :total 39.5} {:_id "NY" :total 697.0}}]
(mc/insert-batch collection batch) (mc/insert-batch db coll batch)
(let [result (set (mc/aggregate "docs" [{$project {:subtotal {$multiply ["$quantity", "$price"]} (let [result (set (mc/aggregate db coll [{$project {:subtotal {$multiply ["$quantity", "$price"]}
:_id 1 :_id 1
:state 1}} :state 1}}
{$group {:_id "$state" {$group {:_id "$state"
@ -69,20 +71,18 @@
(is (= expected result))))) (is (= expected result)))))
(deftest test-$first-aggregation-operator (deftest test-$first-aggregation-operator
(let [collection "docs" (let [batch [{ :state "CA" }
batch [{ :state "CA" }
{ :state "IL"}] { :state "IL"}]
expected "CA"] expected "CA"]
(mc/insert-batch collection batch) (mc/insert-batch db coll batch)
(let [result (:state (first (mc/aggregate collection [{$group { :_id 1 :state {$first "$state"} }}])))] (let [result (:state (first (mc/aggregate db coll [{$group { :_id 1 :state {$first "$state"} }}])))]
(is (= expected result))))) (is (= expected result)))))
(deftest test-$last-aggregation-operator (deftest test-$last-aggregation-operator
(let [collection "docs" (let [batch [{ :state "CA" }
batch [{ :state "CA" }
{ :state "IL"}] { :state "IL"}]
expected "IL"] expected "IL"]
(mc/insert-batch collection batch) (mc/insert-batch db coll batch)
(let [result (:state (first (mc/aggregate collection [{$group { :_id 1 :state {$last "$state"} }}])))] (let [result (:state (first (mc/aggregate db coll [{$group { :_id 1 :state {$last "$state"} }}])))]
(is (= expected result))))) (is (= expected result))))))

View file

@ -1,365 +1,400 @@
(ns monger.test.atomic-modifiers-test (ns monger.test.atomic-modifiers-test
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject] (:import [com.mongodb WriteResult WriteConcern DBObject]
[org.bson.types ObjectId] [org.bson.types ObjectId]
[java.util Date]) java.util.Date)
(:require [monger core util] (:require [monger.core :as mg]
[monger.collection :as mgcol] [monger.collection :as mc]
[monger.result :as mgres] [monger.result :as mgres]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]))
[monger.test.fixtures :refer :all]))
(helper/connect!)
(use-fixtures :each purge-docs purge-things purge-scores)
;; (let [conn (mg/connect)
;; $inc db (mg/get-db conn "monger-test")]
;;
(deftest increment-a-single-existing-field-using-$inc-modifier (defn purge-collections
[f]
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "scores")
(f)
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "scores"))
(use-fixtures :each purge-collections)
;;
;; $inc
;;
(deftest increment-a-single-existing-field-using-$inc-modifier
(let [coll "scores" (let [coll "scores"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :username "l33r0y" :score 100 }) (mc/insert db coll { :_id oid :username "l33r0y" :score 100 })
(mgcol/update coll { :_id oid } { $inc { :score 20 } }) (mc/update db coll { :_id oid } { $inc { :score 20 } })
(is (= 120 (:score (mgcol/find-map-by-id coll oid)))))) (is (= 120 (:score (mc/find-map-by-id db coll oid))))))
(deftest set-a-single-non-existing-field-using-$inc-modifier (deftest set-a-single-non-existing-field-using-$inc-modifier
(let [coll "scores" (let [coll "scores"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :username "l33r0y" }) (mc/insert db coll { :_id oid :username "l33r0y" })
(mgcol/update coll { :_id oid } { $inc { :score 30 } }) (mc/update db coll { :_id oid } { $inc { :score 30 } })
(is (= 30 (:score (mgcol/find-map-by-id coll oid)))))) (is (= 30 (:score (mc/find-map-by-id db coll oid))))))
(deftest increment-multiple-existing-fields-using-$inc-modifier (deftest increment-multiple-existing-fields-using-$inc-modifier
(let [coll "scores" (let [coll "scores"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :username "l33r0y" :score 100 :bonus 0 }) (mc/insert db coll { :_id oid :username "l33r0y" :score 100 :bonus 0 })
(mgcol/update coll { :_id oid } {$inc { :score 20 :bonus 10 } }) (mc/update db coll { :_id oid } {$inc { :score 20 :bonus 10 } })
(is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" }
(mc/find-map-by-id db coll oid)))))
(deftest increment-and-set-multiple-existing-fields-using-$inc-modifier (deftest increment-and-set-multiple-existing-fields-using-$inc-modifier
(let [coll "scores" (let [coll "scores"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :username "l33r0y" :score 100 }) (mc/insert db coll { :_id oid :username "l33r0y" :score 100 })
(mgcol/update coll { :_id oid } { $inc { :score 20 :bonus 10 } }) (mc/update db coll { :_id oid } { $inc { :score 20 :bonus 10 } })
(is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" }
(mc/find-map-by-id db coll oid)))))
;; ;;
;; $set ;; $set
;; ;;
(deftest update-a-single-existing-field-using-$set-modifier (deftest update-a-single-existing-field-using-$set-modifier
(let [coll "things" (let [coll "things"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :weight 10.0 }) (mc/insert db coll { :_id oid :weight 10.0 })
(mgcol/update coll { :_id oid } { $set { :weight 20.5 } }) (mc/update db coll { :_id oid } { $set { :weight 20.5 } })
(is (= 20.5 (:weight (mgcol/find-map-by-id coll oid [:weight])))))) (is (= 20.5 (:weight (mc/find-map-by-id db coll oid [:weight]))))))
(deftest set-a-single-non-existing-field-using-$set-modifier (deftest set-a-single-non-existing-field-using-$set-modifier
(let [coll "things" (let [coll "things"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :weight 10.0 }) (mc/insert db coll { :_id oid :weight 10.0 })
(mgcol/update coll { :_id oid } { $set { :height 17.2 } }) (mc/update db coll { :_id oid } { $set { :height 17.2 } })
(is (= 17.2 (:height (mgcol/find-map-by-id coll oid [:height])))))) (is (= 17.2 (:height (mc/find-map-by-id db coll oid [:height]))))))
(deftest update-multiple-existing-fields-using-$set-modifier (deftest update-multiple-existing-fields-using-$set-modifier
(let [coll "things" (let [coll "things"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :weight 10.0 :height 15.2 }) (mc/insert db coll { :_id oid :weight 10.0 :height 15.2 })
(mgcol/update coll { :_id oid } { $set { :weight 20.5 :height 25.6 } }) (mc/update db coll { :_id oid } { $set { :weight 20.5 :height 25.6 } })
(is (= { :_id oid :weight 20.5 :height 25.6 } (mgcol/find-map-by-id coll oid [:weight :height]))))) (is (= { :_id oid :weight 20.5 :height 25.6 }
(mc/find-map-by-id db coll oid [:weight :height])))))
(deftest update-and-set-multiple-fields-using-$set-modifier (deftest update-and-set-multiple-fields-using-$set-modifier
(let [coll "things" (let [coll "things"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :weight 10.0 }) (mc/insert db coll { :_id oid :weight 10.0 })
(mgcol/update coll { :_id oid } {$set { :weight 20.5 :height 25.6 } }) (mc/update db coll { :_id oid } {$set { :weight 20.5 :height 25.6 } })
(is (= { :_id oid :weight 20.5 :height 25.6 } (mgcol/find-map-by-id coll oid [:weight :height]))))) (is (= { :_id oid :weight 20.5 :height 25.6 }
(mc/find-map-by-id db coll oid [:weight :height])))))
;; ;;
;; $unset ;; $unset
;; ;;
(deftest unset-a-single-existing-field-using-$unset-modifier (deftest unset-a-single-existing-field-using-$unset-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :title "Document 1" :published true }) (mc/insert db coll { :_id oid :title "Document 1" :published true })
(mgcol/update coll { :_id oid } { $unset { :published 1 } }) (mc/update db coll { :_id oid } { $unset { :published 1 } })
(is (= { :_id oid :title "Document 1" } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title "Document 1" }
(mc/find-map-by-id db coll oid)))))
(deftest unset-multiple-existing-fields-using-$unset-modifier (deftest unset-multiple-existing-fields-using-$unset-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :title "Document 1" :published true :featured true }) (mc/insert db coll { :_id oid :title "Document 1" :published true :featured true })
(mgcol/update coll { :_id oid } { $unset { :published 1 :featured true } }) (mc/update db coll { :_id oid } { $unset { :published 1 :featured true } })
(is (= { :_id oid :title "Document 1" } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title "Document 1" }
(mc/find-map-by-id db coll oid)))))
(deftest unsetting-an-unexisting-field-using-$unset-modifier-is-not-considered-an-issue (deftest unsetting-an-unexisting-field-using-$unset-modifier-is-not-considered-an-issue
(let [coll "docs" (let [coll "docs"
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :title "Document 1" :published true }) (mc/insert db coll { :_id oid :title "Document 1" :published true })
(is (mgres/ok? (mgcol/update coll { :_id oid } { $unset { :published 1 :featured true } }))) (is (mgres/ok? (mc/update db coll { :_id oid } { $unset { :published 1 :featured true } })))
(is (= { :_id oid :title "Document 1" } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title "Document 1" }
(mc/find-map-by-id db coll oid)))))
;; ;;
;; $setOnInsert ;; $setOnInsert
;; ;;
(deftest setOnInsert-in-upsert-for-non-existing-document (deftest setOnInsert-in-upsert-for-non-existing-document
(let [coll "docs" (let [coll "docs"
now 456 now 456
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/find-and-modify coll {:_id oid} {$set {:lastseen now} $setOnInsert {:firstseen now}} :upsert true) (mc/find-and-modify db coll {:_id oid} {$set {:lastseen now} $setOnInsert {:firstseen now}} {:upsert true})
(is (= { :_id oid :lastseen now :firstseen now} (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :lastseen now :firstseen now}
(mc/find-map-by-id db coll oid)))))
(deftest setOnInsert-in-upsert-for-existing-document (deftest setOnInsert-in-upsert-for-existing-document
(let [coll "docs" (let [coll "docs"
before 123 before 123
now 456 now 456
oid (ObjectId.)] oid (ObjectId.)]
(mgcol/insert coll { :_id oid :firstseen before :lastseen before}) (mc/insert db coll { :_id oid :firstseen before :lastseen before})
(mgcol/find-and-modify coll {:_id oid} {$set {:lastseen now} $setOnInsert {:firstseen now}} :upsert true) (mc/find-and-modify db coll {:_id oid} {$set {:lastseen now} $setOnInsert {:firstseen now}} {:upsert true})
(is (= { :_id oid :lastseen now :firstseen before} (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :lastseen now :firstseen before}
(mc/find-map-by-id db coll oid)))))
;; ;;
;; $push ;; $push
;; ;;
(deftest initialize-an-array-using-$push-modifier (deftest initialize-an-array-using-$push-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$push modifier appends value to field"] title "$push modifier appends value to field"]
(mgcol/insert coll { :_id oid :title title }) (mc/insert db coll { :_id oid :title title })
(mgcol/update coll { :_id oid } { $push { :tags "modifiers" } }) (mc/update db coll { :_id oid } { $push { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["modifiers"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["modifiers"] }
(mc/find-map-by-id db coll oid)))))
(deftest add-value-to-an-existing-array-using-$push-modifier (deftest add-value-to-an-existing-array-using-$push-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$push modifier appends value to field"] title "$push modifier appends value to field"]
(mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) (mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update coll { :_id oid } { $push { :tags "modifiers" } }) (mc/update db coll { :_id oid } { $push { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["mongodb" "modifiers"] }
(mc/find-map-by-id db coll oid)))))
;; this is a common mistake, I leave it here to demonstrate it. You almost never ;; this is a common mistake, I leave it here to demonstrate it. You almost never
;; actually want to do this! What you really want is to use $pushAll instead of $push. MK. ;; actually want to do this! What you really want is to use $pushAll instead of $push. MK.
(deftest add-array-value-to-an-existing-array-using-$push-modifier (deftest add-array-value-to-an-existing-array-using-$push-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$push modifier appends value to field"] title "$push modifier appends value to field"]
(mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) (mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update coll { :_id oid } { $push { :tags ["modifiers" "operators"] } }) (mc/update db coll { :_id oid } { $push { :tags ["modifiers" "operators"] } })
(is (= { :_id oid :title title :tags ["mongodb" ["modifiers" "operators"]] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["mongodb" ["modifiers" "operators"]] }
(mc/find-map-by-id db coll oid)))))
(deftest double-add-value-to-an-existing-array-using-$push-modifier (deftest double-add-value-to-an-existing-array-using-$push-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$push modifier appends value to field"] title "$push modifier appends value to field"]
(mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) (mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update coll { :_id oid } { $push { :tags "modifiers" } }) (mc/update db coll { :_id oid } { $push { :tags "modifiers" } })
(mgcol/update coll { :_id oid } { $push { :tags "modifiers" } }) (mc/update db coll { :_id oid } { $push { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers" "modifiers"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["mongodb" "modifiers" "modifiers"] }
(mc/find-map-by-id db coll oid)))))
;; ;;
;; $pushAll ;; $pushAll
;; ;;
(deftest initialize-an-array-using-$pushAll-modifier (deftest initialize-an-array-using-$pushAll-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$pushAll modifier appends multiple values to field"] title "$pushAll modifier appends multiple values to field"]
(mgcol/insert coll { :_id oid :title title }) (mc/insert db coll { :_id oid :title title })
(mgcol/update coll { :_id oid } { $pushAll { :tags ["mongodb" "docs"] } }) (mc/update db coll { :_id oid } { $pushAll { :tags ["mongodb" "docs"] } })
(is (= { :_id oid :title title :tags ["mongodb" "docs"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["mongodb" "docs"] }
(mc/find-map-by-id db coll oid)))))
(deftest add-value-to-an-existing-array-using-$pushAll-modifier (deftest add-value-to-an-existing-array-using-$pushAll-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$pushAll modifier appends multiple values to field"] title "$pushAll modifier appends multiple values to field"]
(mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) (mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } }) (mc/update db coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers" "docs"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["mongodb" "modifiers" "docs"] }
(mc/find-map-by-id db coll oid)))))
(deftest double-add-value-to-an-existing-array-using-$pushAll-modifier (deftest double-add-value-to-an-existing-array-using-$pushAll-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$pushAll modifier appends multiple values to field"] title "$pushAll modifier appends multiple values to field"]
(mgcol/insert coll { :_id oid :title title :tags ["mongodb" "docs"] }) (mc/insert db coll { :_id oid :title title :tags ["mongodb" "docs"] })
(mgcol/update coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } }) (mc/update db coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } })
(is (= { :_id oid :title title :tags ["mongodb" "docs" "modifiers" "docs"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["mongodb" "docs" "modifiers" "docs"] }
(mc/find-map-by-id db coll oid)))))
;; ;;
;; $addToSet ;; $addToSet
;; ;;
(deftest initialize-an-array-using-$addToSet-modifier (deftest initialize-an-array-using-$addToSet-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$addToSet modifier appends value to field unless it is already there"] title "$addToSet modifier appends value to field unless it is already there"]
(mgcol/insert coll { :_id oid :title title }) (mc/insert db coll { :_id oid :title title })
(mgcol/update coll { :_id oid } { $addToSet { :tags "modifiers" } }) (mc/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["modifiers"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["modifiers"] }
(mc/find-map-by-id db coll oid)))))
(deftest add-value-to-an-existing-array-using-$addToSet-modifier (deftest add-value-to-an-existing-array-using-$addToSet-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$addToSet modifier appends value to field unless it is already there"] title "$addToSet modifier appends value to field unless it is already there"]
(mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) (mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update coll { :_id oid } { $addToSet { :tags "modifiers" } }) (mc/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["mongodb" "modifiers"] }
(mc/find-map-by-id db coll oid)))))
(deftest double-add-value-to-an-existing-array-using-$addToSet-modifier (deftest double-add-value-to-an-existing-array-using-$addToSet-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$addToSet modifier appends value to field unless it is already there"] title "$addToSet modifier appends value to field unless it is already there"]
(mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) (mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update coll { :_id oid } { $addToSet { :tags "modifiers" } }) (mc/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(mgcol/update coll { :_id oid } { $addToSet { :tags "modifiers" } }) (mc/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["mongodb" "modifiers"] }
(mc/find-map-by-id db coll oid)))))
;; ;;
;; $pop ;; $pop
;; ;;
(deftest pop-last-value-in-the-array-using-$pop-modifier (deftest pop-last-value-in-the-array-using-$pop-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$pop modifier removes last or first value in the array"] title "$pop modifier removes last or first value in the array"]
(mgcol/insert coll { :_id oid :title title :tags ["products" "apple" "reviews"] }) (mc/insert db coll { :_id oid :title title :tags ["products" "apple" "reviews"] })
(mgcol/update coll { :_id oid } { $pop { :tags 1 } }) (mc/update db coll { :_id oid } { $pop { :tags 1 } })
(is (= { :_id oid :title title :tags ["products" "apple"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["products" "apple"] }
(mc/find-map-by-id db coll oid)))))
(deftest unshift-first-value-in-the-array-using-$pop-modifier (deftest unshift-first-value-in-the-array-using-$pop-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$pop modifier removes last or first value in the array"] title "$pop modifier removes last or first value in the array"]
(mgcol/insert coll { :_id oid :title title :tags ["products" "apple" "reviews"] }) (mc/insert db coll { :_id oid :title title :tags ["products" "apple" "reviews"] })
(mgcol/update coll { :_id oid } { $pop { :tags -1 } }) (mc/update db coll { :_id oid } { $pop { :tags -1 } })
(is (= { :_id oid :title title :tags ["apple" "reviews"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["apple" "reviews"] }
(mc/find-map-by-id db coll oid)))))
(deftest pop-last-values-from-multiple-arrays-using-$pop-modifier (deftest pop-last-values-from-multiple-arrays-using-$pop-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$pop modifier removes last or first value in the array"] title "$pop modifier removes last or first value in the array"]
(mgcol/insert coll { :_id oid :title title :tags ["products" "apple" "reviews"] :categories ["apple" "reviews" "drafts"] }) (mc/insert db coll { :_id oid :title title :tags ["products" "apple" "reviews"] :categories ["apple" "reviews" "drafts"] })
(mgcol/update coll { :_id oid } { $pop { :tags 1 :categories 1 } }) (mc/update db coll { :_id oid } { $pop { :tags 1 :categories 1 } })
(is (= { :_id oid :title title :tags ["products" "apple"] :categories ["apple" "reviews"] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :tags ["products" "apple"] :categories ["apple" "reviews"] }
(mc/find-map-by-id db coll oid)))))
;; ;;
;; $pull ;; $pull
;; ;;
(deftest remove-all-value-entries-from-array-using-$pull-modifier (deftest remove-all-value-entries-from-array-using-$pull-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$pull modifier removes all value entries in the array"] title "$pull modifier removes all value entries in the array"]
(mgcol/insert coll { :_id oid :title title :measurements [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0] }) (mc/insert db coll { :_id oid :title title :measurements [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0] })
(mgcol/update coll { :_id oid } { $pull { :measurements 1.2 } }) (mc/update db coll { :_id oid } { $pull { :measurements 1.2 } })
(is (= { :_id oid :title title :measurements [1.0 1.1 1.1 1.3 1.0] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :measurements [1.0 1.1 1.1 1.3 1.0] }
(mc/find-map-by-id db coll oid)))))
(deftest remove-all-value-entries-from-array-using-$pull-modifier-based-on-a-condition (deftest remove-all-value-entries-from-array-using-$pull-modifier-based-on-a-condition
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$pull modifier removes all value entries in the array"] title "$pull modifier removes all value entries in the array"]
(mgcol/insert coll { :_id oid :title title :measurements [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0] }) (mc/insert db coll { :_id oid :title title :measurements [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0] })
(mgcol/update coll { :_id oid } { $pull { :measurements { $gte 1.2 } } }) (mc/update db coll { :_id oid } { $pull { :measurements { $gte 1.2 } } })
(is (= { :_id oid :title title :measurements [1.0 1.1 1.1 1.0] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :measurements [1.0 1.1 1.1 1.0] }
;; (mc/find-map-by-id db coll oid)))))
;; $pullAll ;;
;; ;; $pullAll
;;
(deftest remove-all-value-entries-from-array-using-$pullAll-modifier (deftest remove-all-value-entries-from-array-using-$pullAll-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$pullAll modifier removes entries of multiple values in the array"] title "$pullAll modifier removes entries of multiple values in the array"]
(mgcol/insert coll { :_id oid :title title :measurements [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0] }) (mc/insert db coll { :_id oid :title title :measurements [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0] })
(mgcol/update coll { :_id oid } { $pullAll { :measurements [1.0 1.1 1.2] } }) (mc/update db coll { :_id oid } { $pullAll { :measurements [1.0 1.1 1.2] } })
(is (= { :_id oid :title title :measurements [1.3] } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :measurements [1.3] }
(mc/find-map-by-id db coll oid)))))
;; ;;
;; $rename ;; $rename
;; ;;
(deftest rename-a-single-field-using-$rename-modifier (deftest rename-a-single-field-using-$rename-modifier
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
title "$rename renames fields" title "$rename renames fields"
v [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0]] v [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0]]
(mgcol/insert coll { :_id oid :title title :measurements v }) (mc/insert db coll { :_id oid :title title :measurements v })
(mgcol/update coll { :_id oid } { $rename { :measurements "results" } }) (mc/update db coll { :_id oid } { $rename { :measurements "results" } })
(is (= { :_id oid :title title :results v } (mgcol/find-map-by-id coll oid))))) (is (= { :_id oid :title title :results v }
(mc/find-map-by-id db coll oid)))))
;; ;;
;; find-and-modify ;; find-and-modify
;; ;;
(deftest find-and-modify-a-single-document (deftest find-and-modify-a-single-document
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
doc {:_id oid :name "Sophie Bangs" :level 42} doc {:_id oid :name "Sophie Bangs" :level 42}
conditions {:name "Sophie Bangs"} conditions {:name "Sophie Bangs"}
update {$inc {:level 1}}] update {$inc {:level 1}}]
(mgcol/insert coll doc) (mc/insert db coll doc)
(let [res (mgcol/find-and-modify coll conditions update :return-new true)] (let [res (mc/find-and-modify db coll conditions update {:return-new true})]
(is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 43}))))) (is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 43})))))
(deftest find-and-modify-remove-a-document (deftest find-and-modify-remove-a-document
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
doc {:_id oid :name "Sophie Bangs" :level 42} doc {:_id oid :name "Sophie Bangs" :level 42}
conditions {:name "Sophie Bangs"}] conditions {:name "Sophie Bangs"}]
(mgcol/insert coll doc) (mc/insert db coll doc)
(let [res (mgcol/find-and-modify coll conditions {} :remove true)] (let [res (mc/find-and-modify db coll conditions {} {:remove true})]
(is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 42})) (is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 42}))
(is (empty? (mgcol/find-maps coll conditions)))))) (is (empty? (mc/find-maps db coll conditions))))))
(deftest find-and-modify-upsert-a-document (deftest find-and-modify-upsert-a-document
(testing "case 1" (testing "case 1"
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
doc {:_id oid :name "Sophie Bangs" :level 42}] doc {:_id oid :name "Sophie Bangs" :level 42}]
(let [res (mgcol/find-and-modify coll doc doc :upsert true)] (let [res (mc/find-and-modify db coll doc doc {:upsert true})]
(is (empty? res)) (is (empty? res))
(is (select-keys (mgcol/find-map-by-id coll oid) [:name :level]) (dissoc doc :_id))))) (is (select-keys (mc/find-map-by-id db coll oid) [:name :level]) (dissoc doc :_id)))))
(testing "case 2" (testing "case 2"
(let [coll "docs" (let [coll "docs"
query {:name "Sophie Bangs"} query {:name "Sophie Bangs"}
doc (merge query {:level 42})] doc (merge query {:level 42})]
(let [res (mgcol/find-and-modify coll query doc :upsert true :return-new true)] (let [res (mc/find-and-modify db coll query doc {:upsert true :return-new true})]
(is (:_id res)) (is (:_id res))
(is (select-keys (mgcol/find-map-by-id coll (:_id res)) [:name :level]) doc))))) (is (select-keys (mc/find-map-by-id db coll (:_id res)) [:name :level]) doc)))))
(deftest find-and-modify-after-sort (deftest find-and-modify-after-sort
(let [coll "docs" (let [coll "docs"
oid (ObjectId.) oid (ObjectId.)
oid2 (ObjectId.) oid2 (ObjectId.)
doc {:name "Sophie Bangs"} doc {:name "Sophie Bangs"}
doc1 (assoc doc :_id oid :level 42) doc1 (assoc doc :_id oid :level 42)
doc2 (assoc doc :_id oid2 :level 0)] doc2 (assoc doc :_id oid2 :level 0)]
(mgcol/insert-batch coll [doc1 doc2]) (mc/insert-batch db coll [doc1 doc2])
(let [res (mgcol/find-and-modify coll doc {$inc {:level 1}} :sort {:level -1})] (let [res (mc/find-and-modify db coll doc {$inc {:level 1}} {:sort {:level -1}})]
(is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 42}))))) (is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 42}))))))

View file

@ -1,52 +1,53 @@
(ns monger.test.authentication-test (ns monger.test.authentication-test
(:require [monger core util db] (:require [monger util db]
[monger.test.helper :as helper] [monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[clojure.test :refer :all])) [clojure.test :refer :all]))
(helper/connect!) ;;
;; Connection via URI
;;
(when-not (System/getenv "CI") (when-not (System/getenv "CI")
(deftest ^{:authentication true} connect-to-mongo-via-uri-without-credentials (deftest ^{:authentication true} connect-to-mongo-via-uri-without-credentials
(let [connection (monger.core/connect-via-uri! "mongodb://127.0.0.1/monger-test4")] (let [{:keys [conn db]} (mg/connect-via-uri "mongodb://127.0.0.1/monger-test4")]
(is (= (-> connection .getAddress ^InetAddress (.sameHost "127.0.0.1"))))) (is (= (-> conn .getAddress ^InetAddress (.sameHost "127.0.0.1"))))))
;; reconnect using regular host
(helper/connect!))
(deftest ^{:authentication true} connect-to-mongo-via-uri-with-valid-credentials (deftest ^{:authentication true} connect-to-mongo-via-uri-with-valid-credentials
(let [connection (monger.core/connect-via-uri! "mongodb://clojurewerkz/monger:monger@127.0.0.1/monger-test4")] (let [{:keys [conn db]} (mg/connect-via-uri "mongodb://clojurewerkz/monger:monger@127.0.0.1/monger-test4")]
(is (= "monger-test4" (.getName (monger.core/current-db)))) (is (= "monger-test4" (.getName db)))
(is (= (-> connection .getAddress ^InetAddress (.sameHost "127.0.0.1")))) (is (= (-> conn .getAddress ^InetAddress (.sameHost "127.0.0.1"))))
(mc/remove "documents") (mc/remove db "documents")
;; make sure that the database is selected ;; make sure that the database is selected
;; and operations get through. ;; and operations get through.
(mc/insert "documents" {:field "value"}) (mc/insert db "documents" {:field "value"})
(is (= 1 (mc/count "documents" {})))) (is (= 1 (mc/count db "documents" {}))))))
;; reconnect using regular host
(helper/connect!)))
(if-let [uri (System/getenv "MONGOHQ_URL")] (if-let [uri (System/getenv "MONGOHQ_URL")]
(deftest ^{:external true :authentication true} connect-to-mongo-via-uri-with-valid-credentials (deftest ^{:external true :authentication true} connect-to-mongo-via-uri-with-valid-credentials
(let [connection (monger.core/connect-via-uri! uri)] (let [{:keys [conn db]} (mg/connect-via-uri uri)]
(is (= (-> connection .getAddress ^InetAddress (.sameHost "127.0.0.1"))))) (is (= (-> conn .getAddress ^InetAddress (.sameHost "127.0.0.1")))))))
;; reconnect using regular host
(helper/connect!)))
(deftest ^{:authentication true} test-authentication-with-valid-credentials-on-the-default-db ;;
;; Regular connecton
;;
(let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(deftest ^{:authentication true} test-authentication-with-valid-credentials-on-the-default-db
;; see ./bin/ci/before_script.sh. MK. ;; see ./bin/ci/before_script.sh. MK.
(let [username "clojurewerkz/monger" (let [username "clojurewerkz/monger"
pwd "monger"] pwd "monger"]
(is (monger.core/authenticate username (.toCharArray pwd))))) (is (mg/authenticate db username (.toCharArray pwd)))))
(deftest ^{:authentication true} test-authentication-with-valid-credentials-on-an-arbitrary-db (deftest ^{:authentication true} test-authentication-with-valid-credentials-on-an-arbitrary-db
;; see ./bin/ci/before_script.sh. MK. ;; see ./bin/ci/before_script.sh. MK.
(let [username "clojurewerkz/monger" (let [username "clojurewerkz/monger"
pwd "monger"] pwd "monger"]
(is (monger.core/authenticate (monger.core/get-db "monger-test") username (.toCharArray pwd))))) (is (mg/authenticate (mg/get-db conn "monger-test") username (.toCharArray pwd)))))
(deftest ^{:authentication true} test-authentication-with-invalid-credentials (deftest ^{:authentication true} test-authentication-with-invalid-credentials
(let [username "monger" (let [username "monger"
^String pwd (monger.util/random-str 128 32)] ^String pwd (monger.util/random-str 128 32)]
(is (not (monger.core/authenticate (monger.core/get-db "monger-test2") username (.toCharArray pwd)))))) (is (not (mg/authenticate (mg/get-db conn "monger-test2") username (.toCharArray pwd)))))))

View file

@ -1,6 +1,5 @@
(ns monger.test.cache-test (ns monger.test.cache-test
(:require [monger.test.helper :as helper] (:require [monger.core :as mg]
[monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[clojure.core.cache :refer :all] [clojure.core.cache :refer :all]
[clojure.test :refer :all] [clojure.test :refer :all]
@ -83,39 +82,35 @@
;; Tests ;; Tests
;; ;;
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(use-fixtures :each (fn [f] (use-fixtures :each (fn [f]
(mc/remove "basic_monger_cache_entries") (mc/remove db "basic_monger_cache_entries")
(let [db (mg/get-db "altcache")]
(mc/remove db "db_aware_monger_cache_entries" {}))
(f) (f)
(mc/remove "basic_monger_cache_entries") (mc/remove db "basic_monger_cache_entries")))
(let [db (mg/get-db "altcache")]
(mc/remove db "db_aware_monger_cache_entries" {}))))
(deftest ^{:cache true} (deftest ^{:cache true}
test-has?-with-basic-monger-cache test-has?-with-basic-monger-cache
(testing "that has? returns false for misses" (testing "that has? returns false for misses"
(let [coll "basic_monger_cache_entries" (let [coll "basic_monger_cache_entries"
c (basic-monger-cache-factory coll)] c (basic-monger-cache-factory db coll)]
(is (not (has? c (str (UUID/randomUUID))))) (is (not (has? c (str (UUID/randomUUID)))))
(is (not (has? c (str (UUID/randomUUID))))))) (is (not (has? c (str (UUID/randomUUID)))))))
(testing "that has? returns true for hits" (testing "that has? returns true for hits"
(let [coll "basic_monger_cache_entries" (let [coll "basic_monger_cache_entries"
c (basic-monger-cache-factory coll {"a" 1 "b" "cache" "c" 3/4})] c (basic-monger-cache-factory db coll {"a" 1 "b" "cache" "c" 3/4})]
(is (has? c "a")) (is (has? c "a"))
(is (has? c "b")) (is (has? c "b"))
(is (has? c "c")) (is (has? c "c"))
(is (not (has? c "d")))))) (is (not (has? c "d"))))))
(deftest ^{:cache true} (deftest ^{:cache true}
test-lookup-with-basic-moger-cache test-lookup-with-basic-monger-cache
(testing "that lookup returns nil for misses" (testing "that lookup returns nil for misses"
(let [coll "basic_monger_cache_entries" (let [coll "basic_monger_cache_entries"
c (basic-monger-cache-factory coll)] c (basic-monger-cache-factory db coll)]
(are [v] (is (nil? (lookup c v))) (are [v] (is (nil? (lookup c v)))
:missing-key :missing-key
"missing-key" "missing-key"
@ -123,47 +118,9 @@
(testing "that lookup returns cached values for hits" (testing "that lookup returns cached values for hits"
(let [l (Long/valueOf 10000) (let [l (Long/valueOf 10000)
coll "basic_monger_cache_entries" coll "basic_monger_cache_entries"
c (basic-monger-cache-factory coll {:skey "Value" :lkey l "kkey" :keyword})] c (basic-monger-cache-factory db coll {:skey "Value" :lkey l "kkey" :keyword})]
(are [v k] (is (= v (lookup c k))) (are [v k] (is (= v (lookup c k)))
"Value" :skey "Value" :skey
l :lkey l :lkey
"keyword" "kkey")))) "keyword" "kkey")))))
(deftest ^{:cache true}
test-has?-with-db-aware-monger-cache
(testing "that has? returns false for misses"
(let [db (mg/get-db "altcache")
coll "db_aware_monger_cache_entries"
c (db-aware-monger-cache-factory db coll)]
(is (not (has? c (str (UUID/randomUUID)))))
(is (not (has? c (str (UUID/randomUUID)))))))
(testing "that has? returns true for hits"
(let [db (mg/get-db "altcache")
coll "db_aware_monger_cache_entries"
c (db-aware-monger-cache-factory db coll {"a" 1 "b" "cache" "c" 3/4})]
(is (has? c "a"))
(is (has? c "b"))
(is (has? c "c"))
(is (not (has? c "d"))))))
(deftest ^{:cache true}
test-lookup-with-db-aware-moger-cache
(testing "that lookup returns nil for misses"
(let [db (mg/get-db "altcache")
coll "db_aware_monger_cache_entries"
c (db-aware-monger-cache-factory db coll)]
(are [v] (is (nil? (lookup c v)))
:missing-key
"missing-key"
(gensym "missing-key"))))
(testing "that lookup returns cached values for hits"
(let [l (Long/valueOf 10000)
db (mg/get-db "altcache")
coll "db_aware_monger_cache_entries"
c (db-aware-monger-cache-factory db coll {:skey "Value" :lkey l "kkey" :keyword})]
(are [v k] (is (= v (lookup c k)))
"Value" :skey
l :lkey
"keyword" "kkey"))))

View file

@ -1,33 +1,25 @@
(ns monger.test.capped-collections-test (ns monger.test.capped-collections-test
(:require [monger core util] (:require [monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[monger.result :as mres]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]))
[monger.test.fixtures :refer :all]))
(helper/connect!)
(defn- megabytes (defn- megabytes
[^long n] [^long n]
(* n 1024 1024)) (* n 1024 1024))
(let [conn (mg/connect)
;; db (mg/get-db conn "monger-test")]
;; Tests (deftest test-inserting-into-capped-collection
;;
(deftest test-inserting-into-capped-collection
(let [n 1000 (let [n 1000
cname "cached" cname "cached"
_ (mc/drop cname) _ (mc/drop db cname)
coll (mc/create cname {:capped true :size (-> 16 megabytes) :max n})] coll (mc/create db cname {:capped true :size (-> 16 megabytes) :max n})]
(is (= cname (.getName coll))) (is (= cname (.getName coll)))
(mc/insert-batch cname (for [i (range 0 (+ n 100))] {:i i})) (mc/insert-batch db cname (for [i (range 0 (+ n 100))] {:i i}))
(is (= n (mc/count cname))) (is (= n (mc/count db cname)))
;; older elements get replaced by newer ones ;; older elements get replaced by newer ones
(is (not (mc/any? cname {:i 1}))) (is (not (mc/any? db cname {:i 1})))
(is (not (mc/any? cname {:i 5}))) (is (not (mc/any? db cname {:i 5})))
(is (not (mc/any? cname {:i 9}))) (is (not (mc/any? db cname {:i 9})))
(is (mc/any? cname {:i (+ n 80)})))) (is (mc/any? db cname {:i (+ n 80)})))))

View file

@ -1,125 +1,131 @@
(ns monger.test.collection-test (ns monger.test.collection-test
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject MapReduceOutput MapReduceCommand MapReduceCommand$OutputType] (:import org.bson.types.ObjectId
org.bson.types.ObjectId
java.util.Date) java.util.Date)
(:require [monger.core :as mg] (:require [monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[monger.result :as mgres]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]))
[monger.test.fixtures :refer :all]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(use-fixtures :each purge-people purge-docs purge-things purge-libraries) (defn purge-collections
[f]
(mc/remove db "people")
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "libraries")
(f)
(mc/remove db "people")
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "libraries"))
(use-fixtures :each purge-collections)
;; ;;
;; count, remove ;; count, remove
;; ;;
(deftest get-collection-size (deftest get-collection-size
(let [collection "things"] (let [collection "things"]
(is (= 0 (mc/count collection))) (is (= 0 (mc/count db collection)))
(mc/insert-batch collection [{:language "Clojure" :name "langohr"} (mc/insert-batch db collection [{:language "Clojure" :name "langohr"}
{:language "Clojure" :name "monger"} {:language "Clojure" :name "monger"}
{:language "Clojure" :name "incanter"} {:language "Clojure" :name "incanter"}
{:language "Scala" :name "akka"}]) {:language "Scala" :name "akka"}])
(is (= 4 (mc/count collection))) (is (= 4 (mc/count db collection)))
(is (mc/any? collection)) (is (mc/any? db collection))
(is (= 3 (mc/count mg/*mongodb-database* collection {:language "Clojure"}))) (is (= 3 (mc/count db collection {:language "Clojure"})))
(is (mc/any? mg/*mongodb-database* collection {:language "Clojure"})) (is (mc/any? db collection {:language "Clojure"}))
(is (= 1 (mc/count collection {:language "Scala" }))) (is (= 1 (mc/count db collection {:language "Scala" })))
(is (mc/any? collection {:language "Scala"})) (is (mc/any? db collection {:language "Scala"}))
(is (= 0 (mc/count mg/*mongodb-database* collection {:language "Python" }))) (is (= 0 (mc/count db collection {:language "Python" })))
(is (not (mc/any? mg/*mongodb-database* collection {:language "Python"}))))) (is (not (mc/any? db collection {:language "Python"})))))
(deftest remove-all-documents-from-collection (deftest remove-all-documents-from-collection
(let [collection "libraries"] (let [collection "libraries"]
(mc/insert-batch collection [{:language "Clojure" :name "monger"} (mc/insert-batch db collection [{:language "Clojure" :name "monger"}
{:language "Clojure" :name "langohr"} {:language "Clojure" :name "langohr"}
{:language "Clojure" :name "incanter"} {:language "Clojure" :name "incanter"}
{:language "Scala" :name "akka"}]) {:language "Scala" :name "akka"}])
(is (= 4 (mc/count collection))) (is (= 4 (mc/count db collection)))
(mc/remove collection) (mc/remove db collection)
(is (= 0 (mc/count collection))))) (is (= 0 (mc/count db collection)))))
(deftest remove-some-documents-from-collection (deftest remove-some-documents-from-collection
(let [collection "libraries"] (let [collection "libraries"]
(mc/insert-batch collection [{:language "Clojure" :name "monger"} (mc/insert-batch db collection [{:language "Clojure" :name "monger"}
{:language "Clojure" :name "langohr"} {:language "Clojure" :name "langohr"}
{:language "Clojure" :name "incanter"} {:language "Clojure" :name "incanter"}
{:language "Scala" :name "akka"}]) {:language "Scala" :name "akka"}])
(is (= 4 (mc/count collection))) (is (= 4 (mc/count db collection)))
(mc/remove collection {:language "Clojure"}) (mc/remove db collection {:language "Clojure"})
(is (= 1 (mc/count collection))))) (is (= 1 (mc/count db collection)))))
(deftest remove-a-single-document-from-collection (deftest remove-a-single-document-from-collection
(let [collection "libraries" (let [collection "libraries"
oid (ObjectId.)] oid (ObjectId.)]
(mc/insert-batch collection [{:language "Clojure" :name "monger" :_id oid}]) (mc/insert-batch db collection [{:language "Clojure" :name "monger" :_id oid}])
(mc/remove-by-id collection oid) (mc/remove-by-id db collection oid)
(is (= 0 (mc/count collection))) (is (= 0 (mc/count db collection)))
(is (nil? (mc/find-by-id collection oid))))) (is (nil? (mc/find-by-id db collection oid)))))
;; ;;
;; exists?, drop, create ;; exists?, drop, create
;; ;;
(deftest checking-for-collection-existence-when-it-does-not-exist (deftest checking-for-collection-existence-when-it-does-not-exist
(let [collection "widgets"] (let [collection "widgets"]
(mc/drop collection) (mc/drop db collection)
(is (false? (mc/exists? collection))))) (is (false? (mc/exists? db collection)))))
(deftest checking-for-collection-existence-when-it-does-exist (deftest checking-for-collection-existence-when-it-does-exist
(let [collection "widgets"] (let [collection "widgets"]
(mc/drop collection) (mc/drop db collection)
(mc/insert-batch collection [{:name "widget1"} (mc/insert-batch db collection [{:name "widget1"}
{:name "widget2"}]) {:name "widget2"}])
(is (mc/exists? collection)) (is (mc/exists? db collection))
(mc/drop collection) (mc/drop db collection)
(is (false? (mc/exists? collection))) (is (false? (mc/exists? db collection)))
(mc/create "widgets" {:capped true :size 100000 :max 10}) (mc/create db "widgets" {:capped true :size 100000 :max 10})
(is (mc/exists? collection)) (is (mc/exists? db collection))
(mc/rename collection "gadgets") (mc/rename db collection "gadgets")
(is (not (mc/exists? collection))) (is (not (mc/exists? db collection)))
(is (mc/exists? "gadgets")) (is (mc/exists? db "gadgets"))
(mc/drop "gadgets"))) (mc/drop db "gadgets")))
;; ;;
;; any?, empty? ;; any?, empty?
;; ;;
(deftest test-any-on-empty-collection (deftest test-any-on-empty-collection
(let [collection "things"] (let [collection "things"]
(is (not (mc/any? collection))))) (is (not (mc/any? db collection)))))
(deftest test-any-on-non-empty-collection (deftest test-any-on-non-empty-collection
(let [collection "things" (let [collection "things"
_ (mc/insert collection {:language "Clojure" :name "langohr"})] _ (mc/insert db collection {:language "Clojure" :name "langohr"})]
(is (mc/any? "things")) (is (mc/any? db "things" {:language "Clojure"}))))
(is (mc/any? mg/*mongodb-database* "things" {:language "Clojure"}))))
(deftest test-empty-on-empty-collection (deftest test-empty-on-empty-collection
(let [collection "things"] (let [collection "things"]
(is (mc/empty? collection)) (is (mc/empty? db collection))))
(is (mc/empty? mg/*mongodb-database* collection))))
(deftest test-empty-on-non-empty-collection (deftest test-empty-on-non-empty-collection
(let [collection "things" (let [collection "things"
_ (mc/insert collection {:language "Clojure" :name "langohr"})] _ (mc/insert db collection {:language "Clojure" :name "langohr"})]
(is (not (mc/empty? "things"))))) (is (not (mc/empty? db "things")))))
;; ;;
;; distinct ;; distinct
;; ;;
(deftest test-distinct-values (deftest test-distinct-values
(let [collection "widgets" (let [collection "widgets"
batch [{:state "CA" :quantity 1 :price 199.00} batch [{:state "CA" :quantity 1 :price 199.00}
{:state "NY" :quantity 2 :price 199.00} {:state "NY" :quantity 2 :price 199.00}
@ -127,16 +133,16 @@
{:state "IL" :quantity 2 :price 11.50 } {:state "IL" :quantity 2 :price 11.50 }
{:state "CA" :quantity 2 :price 2.95 } {:state "CA" :quantity 2 :price 2.95 }
{:state "IL" :quantity 3 :price 5.50 }]] {:state "IL" :quantity 3 :price 5.50 }]]
(mc/insert-batch collection batch) (mc/insert-batch db collection batch)
(is (= ["CA" "IL" "NY"] (sort (mc/distinct mg/*mongodb-database* collection :state {})))) (is (= ["CA" "IL" "NY"] (sort (mc/distinct db collection :state {}))))
(is (= ["CA" "NY"] (sort (mc/distinct collection :state {:price {$gt 100.00}})))))) (is (= ["CA" "NY"] (sort (mc/distinct db collection :state {:price {$gt 100.00}}))))))
;; ;;
;; miscellenous ;; miscellenous
;; ;;
(deftest test-system-collection-predicate (deftest test-system-collection-predicate
(are [name] (is (mc/system-collection? name)) (are [name] (is (mc/system-collection? name))
"system.indexes" "system.indexes"
"system" "system"
@ -148,4 +154,4 @@
"events" "events"
"accounts" "accounts"
"megacorp_account" "megacorp_account"
"myapp_development")) "myapp_development")))

View file

@ -1,36 +1,34 @@
(ns monger.test.command-test (ns monger.test.command-test
(:require [monger.core :as mg] (:require [monger.core :as mg]
[monger.command :as mcom] [monger.command :as mcom]
[monger.test.helper :as helper]
[monger.collection :as mc] [monger.collection :as mc]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.result :refer [ok?]] [monger.result :refer [ok?]]
[monger.conversion :refer [from-db-object]])) [monger.conversion :refer [from-db-object]]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(deftest ^{:command true} test-reindex-collection
(deftest ^{:command true} test-reindex-collection (let [_ (mc/insert db "test" {:name "Clojure"})
(let [_ (mc/insert "test" {:name "Clojure"}) result (mcom/reindex-collection db "test")]
result (mcom/reindex-collection "test")]
(is (ok? result)) (is (ok? result))
(is (get result "indexes")))) (is (get result "indexes"))))
(deftest ^{:command true} test-server-status (deftest ^{:command true} test-server-status
(let [status (mcom/server-status)] (let [status (mcom/server-status db)]
(is (ok? status)) (is (ok? status))
(is (not-empty status)) (is (not-empty status))
(is (get status "serverUsed")))) (is (get status "serverUsed"))))
(deftest ^{:command true} test-top (deftest ^{:command true} test-top
(let [result (mcom/top)] (let [result (mcom/top conn)]
(is (ok? result)) (is (ok? result))
(is (not-empty result)) (is (not-empty result))
(is (get result "serverUsed")))) (is (get result "serverUsed"))))
(deftest ^{:command true} test-running-is-master-as-an-arbitrary-command (deftest ^{:command true} test-running-is-master-as-an-arbitrary-command
(let [raw (mg/command {:isMaster 1}) (let [raw (mg/command db {:isMaster 1})
result (from-db-object raw true)] result (from-db-object raw true)]
(is (ok? result)) (is (ok? result))
(is (ok? raw)) (is (ok? raw))
(is (:ismaster result)))) (is (:ismaster result)))))

View file

@ -1,30 +1,27 @@
(ns monger.test.core-test (ns monger.test.core-test
(:require [monger core collection util result] (:require [monger util result]
[monger.test.helper :as helper] [monger.core :as mg :refer [server-address mongo-options]]
[monger.collection :as mc] [monger.collection :as mc]
[clojure.test :refer :all] [clojure.test :refer :all])
[monger.core :refer [server-address mongo-options]])
(:import [com.mongodb MongoClient DB WriteConcern MongoClientOptions ServerAddress])) (:import [com.mongodb MongoClient DB WriteConcern MongoClientOptions ServerAddress]))
(println (str "Using Clojure version " *clojure-version*)) (println (str "Using Clojure version " *clojure-version*))
(helper/connect!)
(deftest connect-to-mongo-with-default-host-and-port (deftest connect-to-mongo-with-default-host-and-port
(let [connection (monger.core/connect)] (let [connection (mg/connect)]
(is (instance? com.mongodb.MongoClient connection)))) (is (instance? com.mongodb.MongoClient connection))))
(deftest connect-and-disconnect (deftest connect-and-disconnect
(monger.core/connect!) (let [conn (mg/connect)]
(monger.core/disconnect!) (mg/disconnect conn)))
(monger.core/connect!))
(deftest connect-to-mongo-with-default-host-and-explicit-port (deftest connect-to-mongo-with-default-host-and-explicit-port
(let [connection (monger.core/connect { :port 27017 })] (let [connection (mg/connect { :port 27017 })]
(is (instance? com.mongodb.MongoClient connection)))) (is (instance? com.mongodb.MongoClient connection))))
(deftest connect-to-mongo-with-default-port-and-explicit-host (deftest connect-to-mongo-with-default-port-and-explicit-host
(let [connection (monger.core/connect { :host "127.0.0.1" })] (let [connection (mg/connect { :host "127.0.0.1" })]
(is (instance? com.mongodb.MongoClient connection)))) (is (instance? com.mongodb.MongoClient connection))))
(deftest test-server-address (deftest test-server-address
@ -36,31 +33,32 @@
(deftest use-existing-mongo-connection (deftest use-existing-mongo-connection
(let [^MongoClientOptions opts (mongo-options :threads-allowed-to-block-for-connection-multiplier 300) (let [^MongoClientOptions opts (mongo-options :threads-allowed-to-block-for-connection-multiplier 300)
connection (MongoClient. "127.0.0.1" opts)] connection (MongoClient. "127.0.0.1" opts)
(monger.core/set-connection! connection) db (mg/get-db connection "monger-test")]
(is (= monger.core/*mongodb-connection* connection)))) (mg/disconnect connection)))
(deftest connect-to-mongo-with-extra-options (deftest connect-to-mongo-with-extra-options
(let [^MongoClientOptions opts (mongo-options :threads-allowed-to-block-for-connection-multiplier 300) (let [^MongoClientOptions opts (mongo-options :threads-allowed-to-block-for-connection-multiplier 300)
^ServerAddress sa (server-address "127.0.0.1" 27017)] ^ServerAddress sa (server-address "127.0.0.1" 27017)
(monger.core/connect! sa opts))) conn (mg/connect sa opts)]
(mg/disconnect conn)))
(deftest get-database (deftest get-database
(let [connection (monger.core/connect) (let [connection (mg/connect)
db (monger.core/get-db connection "monger-test")] db (mg/get-db connection "monger-test")]
(is (instance? com.mongodb.DB db)))) (is (instance? com.mongodb.DB db))))
(deftest test-get-db-names (deftest test-get-db-names
(let [dbs (monger.core/get-db-names)] (let [conn (mg/connect)
dbs (mg/get-db-names conn)]
(is (not (empty? dbs))) (is (not (empty? dbs)))
(is (dbs "monger-test")))) (is (dbs "monger-test"))))
(deftest get-last-error (deftest get-last-error
(let [connection (monger.core/connect) (let [connection (mg/connect)
db (monger.core/get-db connection "monger-test")] db (mg/get-db connection "monger-test")]
(is (monger.result/ok? (monger.core/get-last-error))) (is (monger.result/ok? (mg/get-last-error db)))
(is (monger.result/ok? (monger.core/get-last-error db))) (is (monger.result/ok? (mg/get-last-error db WriteConcern/NORMAL)))
(is (monger.result/ok? (monger.core/get-last-error db WriteConcern/NORMAL))) (is (monger.result/ok? (mg/get-last-error db 1 100 true)))))
(is (monger.result/ok? (monger.core/get-last-error db 1 100 true)))))

View file

@ -1,19 +1,18 @@
(ns monger.test.cursor-test (ns monger.test.cursor-test
(:import [com.mongodb DBCursor DBObject Bytes] (:import [com.mongodb DBCursor DBObject Bytes]
[java.util List Map]) [java.util List Map])
(:require [monger.test.helper :as helper] (:require [monger.core :as mg]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.cursor :refer :all] [monger.cursor :refer :all]))
[monger.test.fixtures :refer :all]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(deftest make-db-cursor-for-collection (deftest make-db-cursor-for-collection
(is (= DBCursor (is (= DBCursor
(class (make-db-cursor :docs))))) (class (make-db-cursor db :docs)))))
(deftest getting-cursor-options-value (deftest getting-cursor-options-value
(let [db-cur (make-db-cursor :docs) (let [db-cur (make-db-cursor db :docs)
opts (get-options db-cur)] opts (get-options db-cur)]
(is (= true (isa? (class opts) Map))) (is (= true (isa? (class opts) Map)))
(is (= 0 (.getOptions db-cur))) ;;test default value (is (= 0 (.getOptions db-cur))) ;;test default value
@ -24,8 +23,8 @@
(is (= false (:slaveok opts))) (is (= false (:slaveok opts)))
(is (= false (:tailable opts))))) (is (= false (:tailable opts)))))
(deftest adding-option-to-cursor (deftest adding-option-to-cursor
(let [db-cur (make-db-cursor :docs)] (let [db-cur (make-db-cursor db :docs)]
(add-option! db-cur :notimeout) (add-option! db-cur :notimeout)
(is (= (:notimeout cursor-options) (is (= (:notimeout cursor-options)
(.getOptions db-cur))) (.getOptions db-cur)))
@ -36,8 +35,8 @@
(:tailable cursor-options) (:tailable cursor-options)
(:awaitdata cursor-options)))))) (:awaitdata cursor-options))))))
(deftest remove-option-from-cursor (deftest remove-option-from-cursor
(let [db-cur (make-db-cursor :docs)] (let [db-cur (make-db-cursor db :docs)]
(add-option! db-cur :partial) (add-option! db-cur :partial)
(add-option! db-cur :awaitdata) (add-option! db-cur :awaitdata)
;; removing not-set option should not affect result ;; removing not-set option should not affect result
@ -51,16 +50,16 @@
(:partial cursor-options))))) (:partial cursor-options)))))
(deftest test-reset-options (deftest test-reset-options
(let [db-cur (make-db-cursor :docs)] (let [db-cur (make-db-cursor db :docs)]
(add-option! db-cur :partial) (add-option! db-cur :partial)
(is (= (.getOptions db-cur) (is (= (.getOptions db-cur)
(:partial cursor-options))) (:partial cursor-options)))
(is (= 0 (is (= 0
(int (.getOptions (reset-options db-cur))))))) (int (.getOptions (reset-options db-cur)))))))
(deftest add-options-with-hashmap (deftest add-options-with-hashmap
(let [db-cur (make-db-cursor :docs) (let [db-cur (make-db-cursor db :docs)
_ (add-options db-cur {:notimeout true :slaveok true}) _ (add-options db-cur {:notimeout true :slaveok true})
opts (get-options db-cur)] opts (get-options db-cur)]
(is (= true (:notimeout opts))) (is (= true (:notimeout opts)))
@ -68,8 +67,8 @@
(is (= false (:tailable opts))) (is (= false (:tailable opts)))
(is (= false (:oplogreplay opts))))) (is (= false (:oplogreplay opts)))))
(deftest add-options-with-hashmap-and-remove-option (deftest add-options-with-hashmap-and-remove-option
(let [db-cur (make-db-cursor :docs) (let [db-cur (make-db-cursor db :docs)
_ (add-options db-cur {:notimeout true :slaveok true}) _ (add-options db-cur {:notimeout true :slaveok true})
opts (get-options db-cur)] opts (get-options db-cur)]
(is (= true (:notimeout opts))) (is (= true (:notimeout opts)))
@ -82,8 +81,8 @@
(is (= false (:slaveok opts))) (is (= false (:slaveok opts)))
(is (= false (:tailable opts)))))) (is (= false (:tailable opts))))))
(deftest add-options-with-list (deftest add-options-with-list
(let [db-cur (make-db-cursor :docs) (let [db-cur (make-db-cursor db :docs)
_ (add-options db-cur [:notimeout :slaveok]) _ (add-options db-cur [:notimeout :slaveok])
opts (get-options db-cur)] opts (get-options db-cur)]
(is (= true (:notimeout opts))) (is (= true (:notimeout opts)))
@ -91,8 +90,8 @@
(is (= false (:tailable opts))) (is (= false (:tailable opts)))
(is (= false (:oplogreplay opts))))) (is (= false (:oplogreplay opts)))))
(deftest add-options-with-Bytes (deftest add-options-with-Bytes
(let [db-cur (make-db-cursor :docs) (let [db-cur (make-db-cursor db :docs)
_ (add-options db-cur Bytes/QUERYOPTION_NOTIMEOUT) _ (add-options db-cur Bytes/QUERYOPTION_NOTIMEOUT)
opts (get-options db-cur)] opts (get-options db-cur)]
(is (= true (:notimeout opts))) (is (= true (:notimeout opts)))
@ -100,11 +99,11 @@
(is (= false (:tailable opts))) (is (= false (:tailable opts)))
(is (= false (:oplogreplay opts))))) (is (= false (:oplogreplay opts)))))
(deftest add-options-with-one-keyword (deftest add-options-with-one-keyword
(let [db-cur (make-db-cursor :docs) (let [db-cur (make-db-cursor db :docs)
_ (add-options db-cur :notimeout) _ (add-options db-cur :notimeout)
opts (get-options db-cur)] opts (get-options db-cur)]
(is (= true (:notimeout opts))) (is (= true (:notimeout opts)))
(is (= false (:slaveok opts))) (is (= false (:slaveok opts)))
(is (= false (:tailable opts))) (is (= false (:tailable opts)))
(is (= false (:oplogreplay opts))))) (is (= false (:oplogreplay opts))))))

View file

@ -1,44 +1,31 @@
(ns monger.test.db-test (ns monger.test.db-test
(:require [monger core db] (:require [monger.db :as mdb]
[monger.test.helper :as helper] [monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[clojure.test :refer :all]) [clojure.test :refer :all])
(:import [com.mongodb Mongo DB] (:import [com.mongodb Mongo DB]
java.util.Set)) java.util.Set))
(helper/connect!)
;; do not run this test for CI, it complicates matters by messing up ;; do not run this test for CI, it complicates matters by messing up
;; authentication for some other tests :( MK. ;; authentication for some other tests :( MK.
(when-not (System/getenv "CI") (let [conn (mg/connect)]
(when-not (System/getenv "CI")
(deftest test-drop-database (deftest test-drop-database
;; drop a secondary database here. MK. ;; drop a secondary database here. MK.
(monger.core/with-db (monger.core/get-db "monger-test3") (let [db (mg/get-db conn "monger-test3")
(let [collection "test" collection "test"
_ (mc/insert collection {:name "Clojure"}) _ (mc/insert db collection {:name "Clojure"})
check (mc/count collection) check (mc/count db collection)
_ (monger.db/drop-db)] _ (mdb/drop-db db)]
(is (= 1 check)) (is (= 1 check))
(is (not (mc/exists? collection))) (is (not (mc/exists? db collection)))
(is (= 0 (mc/count collection)))))) (is (= 0 (mc/count db collection))))))
(deftest test-use-database (deftest test-get-collection-names
(monger.core/use-db! "monger-test5") (let [db (mg/get-db conn "monger-test")]
(is (= "monger-test5" (.getName (monger.core/current-db)))) (mc/insert db "test-1" {:name "Clojure"})
(let [collection "test" (mc/insert db "test-2" {:name "Clojure"})
_ (mc/insert collection {:name "Clojure"}) (let [^Set xs (mdb/get-collection-names db)]
check (mc/count collection) (is (.contains xs "test-1"))
_ (monger.db/drop-db)] (is (.contains xs "test-2"))))))
(is (= 1 check))
(is (not (mc/exists? collection)))
(is (= 0 (mc/count collection))))))
(deftest test-get-collection-names
(mc/insert "test-1" {:name "Clojure"})
(mc/insert "test-2" {:name "Clojure"})
(let [^Set collections (monger.db/get-collection-names)]
(is (.contains collections "test-1"))
(is (.contains collections "test-2"))))

View file

@ -1,21 +0,0 @@
(ns monger.test.fixtures
(:require [monger.testkit :refer [defcleaner]]))
;;
;; fixture functions
;;
(defcleaner people "people")
(defcleaner docs "docs")
(defcleaner finder-docs "regular_finders_docs")
(defcleaner querying-docs "querying_docs")
(defcleaner things "things")
(defcleaner libraries "libraries")
(defcleaner scores "scores")
(defcleaner locations "locations")
(defcleaner domains "domains")
(defcleaner pages "pages")
(defcleaner cached "cached")
(defcleaner migrations "meta.migrations")

View file

@ -3,33 +3,38 @@
[monger.collection :as mc] [monger.collection :as mc]
[monger.search :as ms] [monger.search :as ms]
[monger.command :as cmd] [monger.command :as cmd]
[monger.test.helper :as helper]
[clojure.test :refer [deftest is use-fixtures]] [clojure.test :refer [deftest is use-fixtures]]
[monger.test.fixtures :refer :all]
[monger.result :refer [ok?]]) [monger.result :refer [ok?]])
(:import com.mongodb.BasicDBObjectBuilder)) (:import com.mongodb.BasicDBObjectBuilder))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")
coll "search-docs"]
(defn enable-search (defn enable-search
[f] [f]
;; {:textSearchEnabled true :setParameter 1} ;; {:textSearchEnabled true :setParameter 1}
(let [bldr (doto (BasicDBObjectBuilder.) (let [bldr (doto (BasicDBObjectBuilder.)
(.append "setParameter" 1) (.append "setParameter" 1)
(.append "textSearchEnabled" true)) (.append "textSearchEnabled" true))
cmd (.get bldr)] cmd (.get bldr)]
(is (ok? (cmd/raw-admin-command cmd)))) (is (ok? (cmd/raw-admin-command conn cmd))))
(f)) (f))
(use-fixtures :each purge-docs) (defn purge-collections
(use-fixtures :once enable-search) [f]
(mc/purge-many db [coll])
(f)
(mc/purge-many db [coll]))
(deftest ^{:search true} test-basic-full-text-search-query (use-fixtures :each purge-collections)
(let [coll "docs"] (use-fixtures :once enable-search)
(mc/ensure-index coll (array-map :subject "text" :content "text"))
(mc/insert coll {:subject "hello there" :content "this should be searchable"}) (deftest ^{:search true} test-basic-full-text-search-query
(mc/insert coll {:subject "untitled" :content "this is just noize"}) (mc/ensure-index db coll (array-map :subject "text" :content "text"))
(let [res (ms/search coll "hello") (mc/insert db coll {:subject "hello there" :content "this should be searchable"})
(mc/insert db coll {:subject "untitled" :content "this is just noize"})
(let [res (ms/search db coll "hello")
xs (ms/results-from res)] xs (ms/results-from res)]
(is (= "hello there" (-> xs first :obj :subject))) (is (= "hello there" (-> xs first :obj :subject)))
(is (= 1.0 (-> xs first :score)))))) (is (= 1.0 (-> xs first :score))))))

View file

@ -1,107 +1,104 @@
(ns monger.test.gridfs-test (ns monger.test.gridfs-test
(:refer-clojure :exclude [count remove find]) (:refer-clojure :exclude [count remove find])
(:require [monger.gridfs :as gridfs] (:require [monger.gridfs :as gridfs]
[monger.test.helper :as helper]
[clojure.java.io :as io] [clojure.java.io :as io]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.core :refer [count]] [monger.core :as mg :refer [count]]
[monger.test.fixtures :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]
[monger.conversion :refer :all] [monger.conversion :refer :all]
[monger.gridfs :refer [store make-input-file store-file filename content-type metadata]]) [monger.gridfs :refer [store make-input-file store-file filename content-type metadata]])
(:import [java.io InputStream File FileInputStream] (:import [java.io InputStream File FileInputStream]
[com.mongodb.gridfs GridFS GridFSInputFile GridFSDBFile])) [com.mongodb.gridfs GridFS GridFSInputFile GridFSDBFile]))
(defn purge-gridfs* (let [conn (mg/connect)
db (mg/get-db conn "monger-test")
fs (mg/get-gridfs conn "monger-test")]
(defn purge-gridfs*
[] []
(gridfs/remove-all)) (gridfs/remove-all fs))
(defn purge-gridfs (defn purge-gridfs
[f] [f]
(gridfs/remove-all) (gridfs/remove-all fs)
(f) (f)
(gridfs/remove-all)) (gridfs/remove-all fs))
(use-fixtures :each purge-gridfs) (use-fixtures :each purge-gridfs)
(helper/connect!) (deftest ^{:gridfs true} test-storing-files-to-gridfs-using-relative-fs-paths
(deftest ^{:gridfs true} test-storing-files-to-gridfs-using-relative-fs-paths
(let [input "./test/resources/mongo/js/mapfun1.js"] (let [input "./test/resources/mongo/js/mapfun1.js"]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store (make-input-file input) (store (make-input-file fs input)
(.setFilename "monger.test.gridfs.file1") (.setFilename "monger.test.gridfs.file1")
(.setContentType "application/octet-stream")) (.setContentType "application/octet-stream"))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-storing-files-to-gridfs-using-file-instances (deftest ^{:gridfs true} test-storing-files-to-gridfs-using-file-instances
(let [input (io/as-file "./test/resources/mongo/js/mapfun1.js")] (let [input (io/as-file "./test/resources/mongo/js/mapfun1.js")]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store-file (make-input-file input) (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file2") (filename "monger.test.gridfs.file2")
(content-type "application/octet-stream")) (content-type "application/octet-stream"))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-storing-bytes-to-gridfs (deftest ^{:gridfs true} test-storing-bytes-to-gridfs
(let [input (.getBytes "A string") (let [input (.getBytes "A string")
md {:format "raw" :source "AwesomeCamera D95"} md {:format "raw" :source "AwesomeCamera D95"}
fname "monger.test.gridfs.file3" fname "monger.test.gridfs.file3"
ct "application/octet-stream"] ct "application/octet-stream"]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store-file (make-input-file input) (store-file (make-input-file fs input)
(filename fname) (filename fname)
(metadata md) (metadata md)
(content-type "application/octet-stream")) (content-type "application/octet-stream"))
(let [f (first (gridfs/files-as-maps))] (let [f (first (gridfs/files-as-maps fs))]
(is (= ct (:contentType f))) (is (= ct (:contentType f)))
(is (= fname (:filename f))) (is (= fname (:filename f)))
(is (= md (:metadata f)))) (is (= md (:metadata f))))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-storing-files-to-gridfs-using-absolute-fs-paths (deftest ^{:gridfs true} test-storing-files-to-gridfs-using-absolute-fs-paths
(let [tmp-file (File/createTempFile "monger.test.gridfs" "test-storing-files-to-gridfs-using-absolute-fs-paths") (let [tmp-file (File/createTempFile "monger.test.gridfs" "test-storing-files-to-gridfs-using-absolute-fs-paths")
_ (spit tmp-file "Some content") _ (spit tmp-file "Some content")
input (.getAbsolutePath tmp-file)] input (.getAbsolutePath tmp-file)]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store-file (make-input-file input) (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file4") (filename "monger.test.gridfs.file4")
(content-type "application/octet-stream")) (content-type "application/octet-stream"))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-storing-files-to-gridfs-using-input-stream (deftest ^{:gridfs true} test-storing-files-to-gridfs-using-input-stream
(let [tmp-file (File/createTempFile "monger.test.gridfs" "test-storing-files-to-gridfs-using-input-stream") (let [tmp-file (File/createTempFile "monger.test.gridfs" "test-storing-files-to-gridfs-using-input-stream")
_ (spit tmp-file "Some other content")] _ (spit tmp-file "Some other content")]
(is (= 0 (count (gridfs/all-files)))) (is (= 0 (count (gridfs/all-files fs))))
(store-file (make-input-file (FileInputStream. tmp-file)) (store-file fs
(make-input-file (FileInputStream. tmp-file))
(filename "monger.test.gridfs.file4b") (filename "monger.test.gridfs.file4b")
(content-type "application/octet-stream")) (content-type "application/octet-stream"))
(is (= 1 (count (gridfs/all-files)))))) (is (= 1 (count (gridfs/all-files fs))))))
(deftest ^{:gridfs true} test-finding-individual-files-on-gridfs (deftest ^{:gridfs true} test-finding-individual-files-on-gridfs
(testing "gridfs/find-one" (testing "gridfs/find-one"
(purge-gridfs*) (purge-gridfs*)
(let [input "./test/resources/mongo/js/mapfun1.js" (let [input "./test/resources/mongo/js/mapfun1.js"
ct "binary/octet-stream" ct "binary/octet-stream"
fname "monger.test.gridfs.file5" fname "monger.test.gridfs.file5"
md5 "14a09deabb50925a3381315149017bbd" md5 "14a09deabb50925a3381315149017bbd"
stored (store-file (make-input-file input) stored (store-file (make-input-file fs input)
(filename fname) (filename fname)
(content-type ct))] (content-type ct))]
(is (= 1 (count (gridfs/all-files)))) (is (= 1 (count (gridfs/all-files fs))))
(is (:_id stored)) (is (:_id stored))
(is (:uploadDate stored)) (is (:uploadDate stored))
(is (= 62 (:length stored))) (is (= 62 (:length stored)))
(is (= md5 (:md5 stored))) (is (= md5 (:md5 stored)))
(is (= fname (:filename stored))) (is (= fname (:filename stored)))
(is (= ct (:contentType stored))) (is (= ct (:contentType stored)))
(are [a b] (is (= a (:md5 (from-db-object (gridfs/find-one b) true)))) (are [a b] (is (= a (:md5 (from-db-object (gridfs/find-one fs b) true))))
md5 (:_id stored) md5 {:_id (:_id stored)}
md5 fname
md5 (to-db-object {:md5 md5})))) md5 (to-db-object {:md5 md5}))))
(testing "gridfs/find-one-as-map" (testing "gridfs/find-one-as-map"
(purge-gridfs*) (purge-gridfs*)
@ -109,39 +106,38 @@
ct "binary/octet-stream" ct "binary/octet-stream"
fname "monger.test.gridfs.file6" fname "monger.test.gridfs.file6"
md5 "14a09deabb50925a3381315149017bbd" md5 "14a09deabb50925a3381315149017bbd"
stored (store-file (make-input-file input) stored (store-file (make-input-file fs input)
(filename fname) (filename fname)
(metadata (to-db-object {:meta "data"})) (metadata (to-db-object {:meta "data"}))
(content-type ct))] (content-type ct))]
(is (= 1 (count (gridfs/all-files)))) (is (= 1 (count (gridfs/all-files fs))))
(is (:_id stored)) (is (:_id stored))
(is (:uploadDate stored)) (is (:uploadDate stored))
(is (= 62 (:length stored))) (is (= 62 (:length stored)))
(is (= md5 (:md5 stored))) (is (= md5 (:md5 stored)))
(is (= fname (:filename stored))) (is (= fname (:filename stored)))
(is (= ct (:contentType stored))) (is (= ct (:contentType stored)))
(let [m (gridfs/find-one-as-map {:filename fname})] (let [m (gridfs/find-one-as-map fs {:filename fname})]
(is (= {:meta "data"} (:metadata m)))) (is (= {:meta "data"} (:metadata m))))
(are [a query] (is (= a (:md5 (gridfs/find-one-as-map query)))) (are [a query] (is (= a (:md5 (gridfs/find-one-as-map fs query))))
md5 (:_id stored) md5 {:_id (:_id stored)}
md5 fname
md5 {:md5 md5})))) md5 {:md5 md5}))))
(deftest ^{:gridfs true} test-finding-multiple-files-on-gridfs (deftest ^{:gridfs true} test-finding-multiple-files-on-gridfs
(let [input "./test/resources/mongo/js/mapfun1.js" (let [input "./test/resources/mongo/js/mapfun1.js"
ct "binary/octet-stream" ct "binary/octet-stream"
md5 "14a09deabb50925a3381315149017bbd" md5 "14a09deabb50925a3381315149017bbd"
stored1 (store-file (make-input-file input) stored1 (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file6") (filename "monger.test.gridfs.file6")
(content-type ct)) (content-type ct))
stored2 (store-file (make-input-file input) stored2 (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file7") (filename "monger.test.gridfs.file7")
(content-type ct)) (content-type ct))
list1 (gridfs/find "monger.test.gridfs.file6") list1 (gridfs/find-by-filename fs "monger.test.gridfs.file6")
list2 (gridfs/find "monger.test.gridfs.file7") list2 (gridfs/find-by-filename fs "monger.test.gridfs.file7")
list3 (gridfs/find "888000___.monger.test.gridfs.file") list3 (gridfs/find-by-filename fs "888000___.monger.test.gridfs.file")
list4 (gridfs/find { :md5 md5 })] list4 (gridfs/find-by-md5 fs md5)]
(is (= 2 (count (gridfs/all-files)))) (is (= 2 (count (gridfs/all-files fs))))
(are [a b] (is (= (map #(.get ^GridFSDBFile % "_id") a) (are [a b] (is (= (map #(.get ^GridFSDBFile % "_id") a)
(map :_id b))) (map :_id b)))
list1 [stored1] list1 [stored1]
@ -150,18 +146,18 @@
list4 [stored1 stored2]))) list4 [stored1 stored2])))
(deftest ^{:gridfs true} test-removing-multiple-files-from-gridfs (deftest ^{:gridfs true} test-removing-multiple-files-from-gridfs
(let [input "./test/resources/mongo/js/mapfun1.js" (let [input "./test/resources/mongo/js/mapfun1.js"
ct "binary/octet-stream" ct "binary/octet-stream"
md5 "14a09deabb50925a3381315149017bbd" md5 "14a09deabb50925a3381315149017bbd"
stored1 (store-file (make-input-file input) stored1 (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file8") (filename "monger.test.gridfs.file8")
(content-type ct)) (content-type ct))
stored2 (store-file (make-input-file input) stored2 (store-file (make-input-file fs input)
(filename "monger.test.gridfs.file9") (filename "monger.test.gridfs.file9")
(content-type ct))] (content-type ct))]
(is (= 2 (count (gridfs/all-files)))) (is (= 2 (count (gridfs/all-files fs))))
(gridfs/remove { :filename "monger.test.gridfs.file8" }) (gridfs/remove fs { :filename "monger.test.gridfs.file8" })
(is (= 1 (count (gridfs/all-files)))) (is (= 1 (count (gridfs/all-files fs))))
(gridfs/remove { :md5 md5 }) (gridfs/remove fs { :md5 md5 })
(is (= 0 (count (gridfs/all-files)))))) (is (= 0 (count (gridfs/all-files fs)))))))

View file

@ -1,17 +0,0 @@
(ns monger.test.helper
(:require [monger core util])
(:import [com.mongodb WriteConcern]))
(def connected (atom false))
(defn connected?
[]
@connected)
(defn connect!
[]
(when-not (connected?)
(do
(monger.core/connect!)
(monger.core/set-db! (monger.core/get-db "monger-test"))
(monger.core/set-default-write-concern! WriteConcern/SAFE)
(reset! connected true))))

View file

@ -1,53 +1,46 @@
(ns monger.test.indexing-test (ns monger.test.indexing-test
(:import org.bson.types.ObjectId (:import org.bson.types.ObjectId
java.util.Date) java.util.Date)
(:require [monger core util] (:require [monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[monger.test.helper :as helper]
monger.joda-time monger.joda-time
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.test.fixtures :refer :all] [clj-time.core :refer [now seconds ago from-now]]))
[clj-time.core :refer [now secs ago from-now]]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(deftest ^{:indexing true} test-creating-and-dropping-indexes
;;
;; indexes
;;
(deftest ^{:indexing true} test-creating-and-dropping-indexes
(let [collection "libraries"] (let [collection "libraries"]
(mc/drop-indexes collection) (mc/drop-indexes db collection)
(mc/create-index collection { "language" 1 }) (mc/create-index db collection { "language" 1 })
(is (= "language_1" (is (= "language_1"
(:name (second (mc/indexes-on collection))))) (:name (second (mc/indexes-on db collection)))))
(mc/drop-index collection "language_1") (mc/drop-index db collection "language_1")
(mc/create-index collection ["language"]) (mc/create-index db collection ["language"])
(mc/drop-index collection "language_1") (mc/drop-index db collection "language_1")
(is (nil? (second (mc/indexes-on collection)))) (is (nil? (second (mc/indexes-on db collection))))
(mc/ensure-index collection (array-map "language" 1) {:unique true}) (mc/ensure-index db collection (array-map "language" 1) {:unique true})
(is (= "language_1" (is (= "language_1"
(:name (second (mc/indexes-on collection))))) (:name (second (mc/indexes-on db collection)))))
(mc/ensure-index collection (array-map "language" 1)) (mc/ensure-index db collection (array-map "language" 1))
(mc/ensure-index collection (array-map "language" 1) { :unique true }) (mc/ensure-index db collection (array-map "language" 1) { :unique true })
(mc/drop-indexes collection))) (mc/drop-indexes db collection)))
(deftest ^{:indexing true :edge-features true :time-consuming true} test-ttl-collections (deftest ^{:indexing true :time-consuming true} test-ttl-collections
(let [coll "recent_events" (let [coll "recent_events"
ttl 30 ttl 30
sleep 120] sleep 120]
(mc/remove coll) (mc/remove db coll)
(mc/ensure-index coll (array-map :created-at 1) {:expireAfterSeconds ttl}) (mc/ensure-index db coll (array-map :created-at 1) {:expireAfterSeconds ttl})
(dotimes [i 100] (dotimes [i 100]
(mc/insert coll {:type "signup" :created-at (-> i secs ago) :i i})) (mc/insert db coll {:type "signup" :created-at (-> i seconds ago) :i i}))
(dotimes [i 100] (dotimes [i 100]
(mc/insert coll {:type "signup" :created-at (-> i secs from-now) :i i})) (mc/insert db coll {:type "signup" :created-at (-> i seconds from-now) :i i}))
(is (= 200 (mc/count coll {:type "signup"}))) (is (= 200 (mc/count db coll {:type "signup"})))
;; sleep for 65 seconds. MongoDB 2.1.2 seems to run TTLMonitor once per minute, according to ;; sleep for 65 seconds. MongoDB 2.1.2 seems to run TTLMonitor once per minute, according to
;; the log. MK. ;; the log. MK.
(println (format "Now sleeping for %d seconds to test TTL collections!" sleep)) (println (format "Now sleeping for %d seconds to test TTL collections!" sleep))
(Thread/sleep (* sleep 1000)) (Thread/sleep (* sleep 1000))
(println (format "Documents in the TTL collection: %d" (mc/count coll {:type "signup"}))) (println (format "Documents in the TTL collection: %d" (mc/count db coll {:type "signup"})))
(is (< (mc/count coll {:type "signup"}) 100)) (is (< (mc/count db coll {:type "signup"}) 100))
(mc/remove coll))) (mc/remove db coll))))

View file

@ -5,120 +5,129 @@
(:require [monger.core :as mg] (:require [monger.core :as mg]
[monger.util :as mu] [monger.util :as mu]
[monger.collection :as mc] [monger.collection :as mc]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]
[monger.conversion :refer :all] [monger.conversion :refer :all]))
[monger.test.fixtures :refer :all]))
(helper/connect!)
(use-fixtures :each purge-people purge-docs purge-things purge-libraries)
;;
;; insert
;;
(deftest insert-a-basic-document-without-id-and-with-default-write-concern
(let [collection "people"
doc {:name "Joe" :age 30}]
(is (monger.result/ok? (mc/insert "people" doc)))
(is (= 1 (mc/count collection)))))
(deftest insert-a-basic-document-with-explicitly-passed-database-without-id-and-with-default-write-concern
(let [collection "people"
doc {:name "Joe" :age 30}]
(dotimes [n 5]
(is (monger.result/ok? (mc/insert monger.core/*mongodb-database* "people" doc WriteConcern/SAFE))))
(is (= 5 (mc/count collection)))))
(deftest insert-a-basic-document-without-id-and-with-explicit-write-concern
(let [collection "people"
doc {:name "Joe" :age 30}]
(is (monger.result/ok? (mc/insert "people" doc WriteConcern/SAFE)))
(is (= 1 (mc/count collection)))))
(deftest insert-a-basic-db-object-without-id-and-with-default-write-concern
(let [collection "people"
doc (to-db-object {:name "Joe" :age 30})]
(is (nil? (.get ^DBObject doc "_id")))
(mc/insert "people" doc)
(is (not (nil? (monger.util/get-id doc))))))
(deftest insert-a-map-with-id-and-with-default-write-concern
(let [collection "people"
id (ObjectId.)
doc {:name "Joe" :age 30 "_id" id}
result (mc/insert "people" doc)]
(is (= id (monger.util/get-id doc)))))
(deftest insert-a-document-with-clojure-ratio-in-it
(let [collection "widgets"
id (ObjectId.)
doc {:ratio 11/2 "_id" id}
result (mc/insert "widgets" doc)]
(is (= 5.5 (:ratio (mc/find-map-by-id collection id))))))
(deftest insert-a-document-with-clojure-keyword-in-it
(let [collection "widgets"
id (ObjectId.)
doc {:keyword :kwd "_id" id}
result (mc/insert "widgets" doc)]
(is (= (name :kwd) (:keyword (mc/find-map-by-id collection id))))))
(deftest insert-a-document-with-clojure-keyword-in-a-set-in-it
(let [collection "widgets"
id (ObjectId.)
doc {:keyword1 {:keyword2 #{:kw1 :kw2}} "_id" id}
result (mc/insert "widgets" doc)]
(is (= (sort ["kw1" "kw2"])
(sort (get-in (mc/find-map-by-id collection id) [:keyword1 :keyword2]))))))
(defrecord Metrics (defrecord Metrics
[rps eps]) [rps eps])
(deftest insert-a-document-with-clojure-record-in-it (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(defn purge-collections
[f]
(mc/remove db "people")
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "widgets")
(f)
(mc/remove db "people")
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "widgets"))
(use-fixtures :each purge-collections)
;;
;; insert
;;
(deftest insert-a-basic-document-without-id-and-with-default-write-concern
(let [collection "people"
doc {:name "Joe" :age 30}]
(is (monger.result/ok? (mc/insert db collection doc)))
(is (= 1 (mc/count db collection)))))
(deftest insert-a-basic-document-with-explicitly-passed-database-without-id-and-with-default-write-concern
(let [collection "people"
doc {:name "Joe" :age 30}]
(dotimes [n 5]
(is (monger.result/ok? (mc/insert db collection doc WriteConcern/SAFE))))
(is (= 5 (mc/count db collection)))))
(deftest insert-a-basic-document-without-id-and-with-explicit-write-concern
(let [collection "people"
doc {:name "Joe" :age 30}]
(is (monger.result/ok? (mc/insert db collection doc WriteConcern/SAFE)))
(is (= 1 (mc/count db collection)))))
(deftest insert-a-basic-db-object-without-id-and-with-default-write-concern
(let [collection "people"
doc (to-db-object {:name "Joe" :age 30})]
(is (nil? (.get ^DBObject doc "_id")))
(mc/insert db collection doc)
(is (not (nil? (monger.util/get-id doc))))))
(deftest insert-a-map-with-id-and-with-default-write-concern
(let [collection "people"
id (ObjectId.)
doc {:name "Joe" :age 30 "_id" id}
result (mc/insert db collection doc)]
(is (= id (monger.util/get-id doc)))))
(deftest insert-a-document-with-clojure-ratio-in-it
(let [collection "widgets"
id (ObjectId.)
doc {:ratio 11/2 "_id" id}
result (mc/insert db collection doc)]
(is (= 5.5 (:ratio (mc/find-map-by-id db collection id))))))
(deftest insert-a-document-with-clojure-keyword-in-it
(let [collection "widgets"
id (ObjectId.)
doc {:keyword :kwd "_id" id}
result (mc/insert db collection doc)]
(is (= (name :kwd) (:keyword (mc/find-map-by-id db collection id))))))
(deftest insert-a-document-with-clojure-keyword-in-a-set-in-it
(let [collection "widgets"
id (ObjectId.)
doc {:keyword1 {:keyword2 #{:kw1 :kw2}} "_id" id}
result (mc/insert db collection doc)]
(is (= (sort ["kw1" "kw2"])
(sort (get-in (mc/find-map-by-id db collection id) [:keyword1 :keyword2]))))))
(deftest insert-a-document-with-clojure-record-in-it
(let [collection "widgets" (let [collection "widgets"
id (ObjectId.) id (ObjectId.)
doc {:record (Metrics. 10 20) "_id" id} doc {:record (Metrics. 10 20) "_id" id}
result (mc/insert "widgets" doc)] result (mc/insert db collection doc)]
(is (= {:rps 10 :eps 20} (:record (mc/find-map-by-id collection id)))))) (is (= {:rps 10 :eps 20} (:record (mc/find-map-by-id db collection id))))))
(deftest test-insert-a-document-with-dbref (deftest test-insert-a-document-with-dbref
(mc/remove "widgets") (mc/remove db "widgets")
(mc/remove "owners") (mc/remove db "owners")
(let [coll1 "widgets" (let [coll1 "widgets"
coll2 "owners" coll2 "owners"
oid (ObjectId.) oid (ObjectId.)
joe (mc/insert "owners" {:name "Joe" :_id oid}) joe (mc/insert db coll2 {:name "Joe" :_id oid})
dbref (DBRef. (mg/current-db) coll2 oid)] dbref (DBRef. db coll2 oid)]
(mc/insert coll1 {:type "pentagon" :owner dbref}) (mc/insert db coll1 {:type "pentagon" :owner dbref})
(let [fetched (mc/find-one-as-map coll1 {:type "pentagon"}) (let [fetched (mc/find-one-as-map db coll1 {:type "pentagon"})
fo (:owner fetched)] fo (:owner fetched)]
(is (= {:_id oid :name "Joe"} (from-db-object @fo true)))))) (is (= {:_id oid :name "Joe"} (from-db-object @fo true))))))
;; ;;
;; insert-and-return ;; insert-and-return
;; ;;
(deftest insert-and-return-a-basic-document-without-id-and-with-default-write-concern (deftest insert-and-return-a-basic-document-without-id-and-with-default-write-concern
(let [collection "people" (let [collection "people"
doc {:name "Joe" :age 30} doc {:name "Joe" :age 30}
result (mc/insert-and-return :people doc)] result (mc/insert-and-return db collection doc)]
(is (= (:name doc) (is (= (:name doc)
(:name result))) (:name result)))
(is (= (:age doc) (is (= (:age doc)
(:age result))) (:age result)))
(is (:_id result)) (is (:_id result))
(is (= 1 (mc/count collection))))) (is (= 1 (mc/count db collection)))))
(deftest insert-and-return-a-basic-document-without-id-but-with-a-write-concern (deftest insert-and-return-a-basic-document-without-id-but-with-a-write-concern
(let [collection "people" (let [collection "people"
doc {:name "Joe" :age 30 :ratio 3/4} doc {:name "Joe" :age 30 :ratio 3/4}
result (mc/insert-and-return "people" doc WriteConcern/FSYNC_SAFE)] result (mc/insert-and-return db collection doc WriteConcern/FSYNC_SAFE)]
(is (= (:name doc) (is (= (:name doc)
(:name result))) (:name result)))
(is (= (:age doc) (is (= (:age doc)
@ -126,44 +135,44 @@
(is (= (:ratio doc) (is (= (:ratio doc)
(:ratio result))) (:ratio result)))
(is (:_id result)) (is (:_id result))
(is (= 1 (mc/count collection))))) (is (= 1 (mc/count db collection)))))
(deftest insert-and-return-with-a-provided-id (deftest insert-and-return-with-a-provided-id
(let [collection "people" (let [collection "people"
oid (ObjectId.) oid (ObjectId.)
doc {:name "Joe" :age 30 :_id oid} doc {:name "Joe" :age 30 :_id oid}
result (mc/insert-and-return :people doc)] result (mc/insert-and-return db collection doc)]
(is (= (:_id result) (:_id doc) oid)) (is (= (:_id result) (:_id doc) oid))
(is (= 1 (mc/count collection))))) (is (= 1 (mc/count db collection)))))
;; ;;
;; insert-batch ;; insert-batch
;; ;;
(deftest insert-a-batch-of-basic-documents-without-ids-and-with-default-write-concern (deftest insert-a-batch-of-basic-documents-without-ids-and-with-default-write-concern
(let [collection "people" (let [collection "people"
docs [{:name "Joe" :age 30} {:name "Paul" :age 27}]] docs [{:name "Joe" :age 30} {:name "Paul" :age 27}]]
(is (monger.result/ok? (mc/insert-batch "people" docs))) (is (monger.result/ok? (mc/insert-batch db collection docs)))
(is (= 2 (mc/count collection))))) (is (= 2 (mc/count db collection)))))
(deftest insert-a-batch-of-basic-documents-without-ids-and-with-explicit-write-concern (deftest insert-a-batch-of-basic-documents-without-ids-and-with-explicit-write-concern
(let [collection "people" (let [collection "people"
docs [{:name "Joe" :age 30} {:name "Paul" :age 27}]] docs [{:name "Joe" :age 30} {:name "Paul" :age 27}]]
(is (monger.result/ok? (mc/insert-batch "people" docs WriteConcern/NORMAL))) (is (monger.result/ok? (mc/insert-batch db collection docs WriteConcern/NORMAL)))
(is (= 2 (mc/count collection))))) (is (= 2 (mc/count db collection)))))
(deftest insert-a-batch-of-basic-documents-with-explicit-database-without-ids-and-with-explicit-write-concern (deftest insert-a-batch-of-basic-documents-with-explicit-database-without-ids-and-with-explicit-write-concern
(let [collection "people" (let [collection "people"
docs [{:name "Joe" :age 30} {:name "Paul" :age 27}]] docs [{:name "Joe" :age 30} {:name "Paul" :age 27}]]
(dotimes [n 44] (dotimes [n 44]
(is (monger.result/ok? (mc/insert-batch monger.core/*mongodb-database* "people" docs WriteConcern/NORMAL)))) (is (monger.result/ok? (mc/insert-batch db collection docs WriteConcern/NORMAL))))
(is (= 88 (mc/count collection))))) (is (= 88 (mc/count db collection)))))
(deftest insert-a-batch-of-basic-documents-from-a-lazy-sequence (deftest insert-a-batch-of-basic-documents-from-a-lazy-sequence
(let [collection "people" (let [collection "people"
numbers (range 0 1000)] numbers (range 0 1000)]
(is (monger.result/ok? (mc/insert-batch "people" (map (fn [^long l] (is (monger.result/ok? (mc/insert-batch db collection (map (fn [^long l]
{:n l}) {:n l})
numbers)))) numbers))))
(is (= (count numbers) (mc/count collection))))) (is (= (count numbers) (mc/count db collection))))))

View file

@ -1,45 +0,0 @@
(ns monger.test.internal.fn-test
(:require [clojure.test :refer :all]
[monger.internal.fn :refer :all]))
(deftest test-expand-all
(are [i o] (is (= (expand-all i) o))
{ :int (fn [] 1) :str "Clojure" :float (Float/valueOf 11.0) } { :int 1 :str "Clojure" :float (Float/valueOf 11.0 )}
{ :long (fn [] (Long/valueOf 11)) } { :long (Long/valueOf 11) }
{
:i 1
:l (Long/valueOf 1111)
:s "Clojure"
:d (Double/valueOf 11.1)
:f (Float/valueOf 2.5)
:v [1 2 3]
:dyn-v [(fn [] 10) (fn [] 20) (fn [] 30)]
:dyn-i (fn [] 1)
:dyn-s (fn [] "Clojure (expanded)")
:m { :nested "String" }
:dyn-m { :abc (fn [] :abc) :nested { :a { :b { :c (fn [] "d") } } } }
}
{
:i 1
:l (Long/valueOf 1111)
:s "Clojure"
:d (Double/valueOf 11.1)
:f (Float/valueOf 2.5)
:v [1 2 3]
:dyn-v [10 20 30]
:dyn-i 1
:dyn-s "Clojure (expanded)"
:m { :nested "String" }
:dyn-m {
:abc :abc
:nested { :a { :b { :c "d" } } }
}
}))
(deftest test-expand-all-with
(let [expander-fn (fn [f]
(* 3 (f)))]
(are [i o] (is (= (expand-all-with i expander-fn) o))
{ :a 1 :int (fn [] 3) } { :a 1 :int 9 }
{ :v [(fn [] 1) (fn [] 11)] :m { :inner (fn [] 3) } :s "Clojure" } { :v [3 33] :m { :inner 9 } :s "Clojure" })))

View file

@ -1,10 +1,7 @@
(ns monger.test.js-test (ns monger.test.js-test
(:require monger.js (:require monger.js
[monger.test.helper :as helper]
[clojure.test :refer :all])) [clojure.test :refer :all]))
(helper/connect!)
(deftest load-js-resource-using-path-on-the-classpath (deftest load-js-resource-using-path-on-the-classpath
(are [c path] (= c (count (monger.js/load-resource path))) (are [c path] (= c (count (monger.js/load-resource path)))
62 "resources/mongo/js/mapfun1.js" 62 "resources/mongo/js/mapfun1.js"

View file

@ -2,26 +2,22 @@
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject MapReduceOutput MapReduceCommand MapReduceCommand$OutputType] (:import [com.mongodb WriteResult WriteConcern DBCursor DBObject MapReduceOutput MapReduceCommand MapReduceCommand$OutputType]
org.bson.types.ObjectId org.bson.types.ObjectId
java.util.Date) java.util.Date)
(:require [monger core util] (:require [monger.collection :as mc]
[monger.collection :as mc] [monger.core :as mg]
[monger.result :as mgres] [monger.result :as mgres]
[clojurewerkz.support.js :as js] [clojurewerkz.support.js :as js]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]
[monger.conversion :refer :all] [monger.conversion :refer :all]))
[monger.test.fixtures :refer :all]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(use-fixtures :each (fn [f]
(mc/remove db "widgets")
(f)
(mc/remove db "widgets")))
(use-fixtures :each purge-people purge-docs purge-things purge-libraries) (let [collection "widgets"
;;
;; Map/Reduce
;;
(let [collection "widgets"
mapper (js/load-resource "resources/mongo/js/mapfun1.js") mapper (js/load-resource "resources/mongo/js/mapfun1.js")
reducer "function(key, values) { reducer "function(key, values) {
var result = 0; var result = 0;
@ -37,34 +33,34 @@
{ :state "IL" :quantity 3 :price 5.50 }] { :state "IL" :quantity 3 :price 5.50 }]
expected [{:_id "CA", :value 204.9} {:_id "IL", :value 39.5} {:_id "NY", :value 697.0}]] expected [{:_id "CA", :value 204.9} {:_id "IL", :value 39.5} {:_id "NY", :value 697.0}]]
(deftest test-basic-inline-map-reduce-example (deftest test-basic-inline-map-reduce-example
(mc/remove monger.core/*mongodb-database* collection {}) (mc/remove db collection)
(is (mgres/ok? (mc/insert-batch collection batch))) (is (mgres/ok? (mc/insert-batch db collection batch)))
(let [output (mc/map-reduce collection mapper reducer nil MapReduceCommand$OutputType/INLINE {}) (let [output (mc/map-reduce db collection mapper reducer nil MapReduceCommand$OutputType/INLINE {})
results (from-db-object ^DBObject (.results ^MapReduceOutput output) true)] results (from-db-object ^DBObject (.results ^MapReduceOutput output) true)]
(mgres/ok? output) (mgres/ok? output)
(is (= expected results)))) (is (= expected results))))
(deftest test-basic-map-reduce-example-that-replaces-named-collection (deftest test-basic-map-reduce-example-that-replaces-named-collection
(mc/remove monger.core/*mongodb-database* collection {}) (mc/remove db collection)
(is (mgres/ok? (mc/insert-batch collection batch))) (is (mgres/ok? (mc/insert-batch db collection batch)))
(let [output (mc/map-reduce collection mapper reducer "mr_outputs" {}) (let [output (mc/map-reduce db collection mapper reducer "mr_outputs" {})
results (from-db-object ^DBObject (.results ^MapReduceOutput output) true)] results (from-db-object ^DBObject (.results ^MapReduceOutput output) true)]
(mgres/ok? output) (mgres/ok? output)
(is (= 3 (monger.core/count results))) (is (= 3 (mg/count results)))
(is (= expected (is (= expected
(map #(from-db-object % true) (seq results)))) (map #(from-db-object % true) (seq results))))
(is (= expected (is (= expected
(map #(from-db-object % true) (mc/find "mr_outputs")))) (map #(from-db-object % true) (mc/find db "mr_outputs"))))
(.drop ^MapReduceOutput output))) (.drop ^MapReduceOutput output)))
(deftest test-basic-map-reduce-example-that-merged-results-into-named-collection (deftest test-basic-map-reduce-example-that-merged-results-into-named-collection
(mc/remove monger.core/*mongodb-database* collection {}) (mc/remove db collection)
(is (mgres/ok? (mc/insert-batch collection batch))) (is (mgres/ok? (mc/insert-batch db collection batch)))
(mc/map-reduce collection mapper reducer "merged_mr_outputs" MapReduceCommand$OutputType/MERGE {}) (mc/map-reduce db collection mapper reducer "merged_mr_outputs" MapReduceCommand$OutputType/MERGE {})
(is (mgres/ok? (mc/insert collection { :state "OR" :price 17.95 :quantity 4 }))) (is (mgres/ok? (mc/insert db collection { :state "OR" :price 17.95 :quantity 4 })))
(let [^MapReduceOutput output (mc/map-reduce collection mapper reducer "merged_mr_outputs" MapReduceCommand$OutputType/MERGE {})] (let [^MapReduceOutput output (mc/map-reduce db collection mapper reducer "merged_mr_outputs" MapReduceCommand$OutputType/MERGE {})]
(mgres/ok? output) (mgres/ok? output)
(is (= 4 (monger.core/count output))) (is (= 4 (mg/count output)))
(is (= ["CA" "IL" "NY" "OR"] (is (= ["CA" "IL" "NY" "OR"]
(map :_id (mc/find-maps "merged_mr_outputs")))) (map :_id (mc/find-maps db "merged_mr_outputs"))))
(.drop ^MapReduceOutput output)))) (.drop ^MapReduceOutput output)))))

View file

@ -1,409 +0,0 @@
(ns monger.test.multi.atomic-modifiers-test
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject]
[org.bson.types ObjectId]
[java.util Date])
(:require [monger.core :as mg]
[monger core util]
[monger.multi.collection :as mc]
[monger.result :as mgres]
[monger.test.helper :as helper]
[clojure.test :refer :all]
[monger.operators :refer :all]
[monger.test.fixtures :refer :all]))
(helper/connect!)
(def db (mg/get-db "altdb"))
(defn purge-altdb
[f]
(mc/remove db "scores")
(mc/remove db "things")
(mc/remove db "docs")
(f))
(use-fixtures :each purge-altdb)
;;
;; $inc
;;
(deftest increment-a-single-existing-field-using-$inc-modifier
(let [db (mg/get-db "altdb")
coll "scores"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :username "l33r0y" :score 100 })
(mc/update db coll { :_id oid } { $inc { :score 20 } })
(is (= 120 (:score (mc/find-map-by-id db coll oid))))))
(deftest set-a-single-non-existing-field-using-$inc-modifier
(let [db (mg/get-db "altdb")
coll "scores"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :username "l33r0y" })
(mc/update db coll { :_id oid } { $inc { :score 30 } })
(is (= 30 (:score (mc/find-map-by-id db coll oid))))))
(deftest increment-multiple-existing-fields-using-$inc-modifier
(let [db (mg/get-db "altdb")
coll "scores"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :username "l33r0y" :score 100 :bonus 0 })
(mc/update db coll { :_id oid } {$inc { :score 20 :bonus 10 } })
(is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mc/find-map-by-id db coll oid)))))
(deftest increment-and-set-multiple-existing-fields-using-$inc-modifier
(let [db (mg/get-db "altdb")
coll "scores"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :username "l33r0y" :score 100 })
(mc/update db coll { :_id oid } { $inc { :score 20 :bonus 10 } })
(is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mc/find-map-by-id db coll oid)))))
;;
;; $set
;;
(deftest update-a-single-existing-field-using-$set-modifier
(let [db (mg/get-db "altdb")
coll "things"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :weight 10.0 })
(mc/update db coll { :_id oid } { $set { :weight 20.5 } })
(is (= 20.5 (:weight (mc/find-map-by-id db coll oid [:weight]))))))
(deftest set-a-single-non-existing-field-using-$set-modifier
(let [db (mg/get-db "altdb")
coll "things"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :weight 10.0 })
(mc/update db coll { :_id oid } { $set { :height 17.2 } })
(is (= 17.2 (:height (mc/find-map-by-id db coll oid [:height]))))))
(deftest update-multiple-existing-fields-using-$set-modifier
(let [db (mg/get-db "altdb")
coll "things"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :weight 10.0 :height 15.2 })
(mc/update db coll { :_id oid } { $set { :weight 20.5 :height 25.6 } })
(is (= { :_id oid :weight 20.5 :height 25.6 } (mc/find-map-by-id db coll oid [:weight :height])))))
(deftest update-and-set-multiple-fields-using-$set-modifier
(let [db (mg/get-db "altdb")
coll "things"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :weight 10.0 })
(mc/update db coll { :_id oid } {$set { :weight 20.5 :height 25.6 } })
(is (= { :_id oid :weight 20.5 :height 25.6 } (mc/find-map-by-id db coll oid [:weight :height])))))
;;
;; $unset
;;
(deftest unset-a-single-existing-field-using-$unset-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :title "Document 1" :published true })
(mc/update db coll { :_id oid } { $unset { :published 1 } })
(is (= { :_id oid :title "Document 1" } (mc/find-map-by-id db coll oid)))))
(deftest unset-multiple-existing-fields-using-$unset-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :title "Document 1" :published true :featured true })
(mc/update db coll { :_id oid } { $unset { :published 1 :featured true } })
(is (= { :_id oid :title "Document 1" } (mc/find-map-by-id db coll oid)))))
(deftest unsetting-an-unexisting-field-using-$unset-modifier-is-not-considered-an-issue
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)]
(mc/insert db coll { :_id oid :title "Document 1" :published true })
(is (mgres/ok? (mc/update db coll { :_id oid } { $unset { :published 1 :featured true } })))
(is (= { :_id oid :title "Document 1" } (mc/find-map-by-id db coll oid)))))
;;
;; $setOnInsert
;;
(deftest setOnInsert-in-upsert-for-non-existing-document
(let [db (mg/get-db "altdb")
coll "docs"
now 456
oid (ObjectId.)]
(mc/find-and-modify db coll {:_id oid} {$set {:lastseen now} $setOnInsert {:firstseen now}} :upsert true)
(is (= { :_id oid :lastseen now :firstseen now} (mc/find-map-by-id db coll oid)))))
(deftest setOnInsert-in-upsert-for-existing-document
(let [db (mg/get-db "altdb")
coll "docs"
before 123
now 456
oid (ObjectId.)]
(mc/insert db coll { :_id oid :firstseen before :lastseen before})
(mc/find-and-modify db coll {:_id oid} {$set {:lastseen now} $setOnInsert {:firstseen now}} :upsert true)
(is (= { :_id oid :lastseen now :firstseen before} (mc/find-map-by-id db coll oid)))))
;;
;; $push
;;
(deftest initialize-an-array-using-$push-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$push modifier appends value to field"]
(mc/insert db coll { :_id oid :title title })
(mc/update db coll { :_id oid } { $push { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["modifiers"] } (mc/find-map-by-id db coll oid)))))
(deftest add-value-to-an-existing-array-using-$push-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$push modifier appends value to field"]
(mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mc/update db coll { :_id oid } { $push { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mc/find-map-by-id db coll oid)))))
;; this is a common mistake, I leave it here to demonstrate it. You almost never
;; actually want to do this! What you really want is to use $pushAll instead of $push. MK.
(deftest add-array-value-to-an-existing-array-using-$push-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$push modifier appends value to field"]
(mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mc/update db coll { :_id oid } { $push { :tags ["modifiers" "operators"] } })
(is (= { :_id oid :title title :tags ["mongodb" ["modifiers" "operators"]] } (mc/find-map-by-id db coll oid)))))
(deftest double-add-value-to-an-existing-array-using-$push-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$push modifier appends value to field"]
(mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mc/update db coll { :_id oid } { $push { :tags "modifiers" } })
(mc/update db coll { :_id oid } { $push { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers" "modifiers"] } (mc/find-map-by-id db coll oid)))))
;;
;; $pushAll
;;
(deftest initialize-an-array-using-$pushAll-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$pushAll modifier appends multiple values to field"]
(mc/insert db coll { :_id oid :title title })
(mc/update db coll { :_id oid } { $pushAll { :tags ["mongodb" "docs"] } })
(is (= { :_id oid :title title :tags ["mongodb" "docs"] } (mc/find-map-by-id db coll oid)))))
(deftest add-value-to-an-existing-array-using-$pushAll-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$pushAll modifier appends multiple values to field"]
(mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mc/update db coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers" "docs"] } (mc/find-map-by-id db coll oid)))))
(deftest double-add-value-to-an-existing-array-using-$pushAll-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$pushAll modifier appends multiple values to field"]
(mc/insert db coll { :_id oid :title title :tags ["mongodb" "docs"] })
(mc/update db coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } })
(is (= { :_id oid :title title :tags ["mongodb" "docs" "modifiers" "docs"] } (mc/find-map-by-id db coll oid)))))
;;
;; $addToSet
;;
(deftest initialize-an-array-using-$addToSet-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$addToSet modifier appends value to field unless it is already there"]
(mc/insert db coll { :_id oid :title title })
(mc/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["modifiers"] } (mc/find-map-by-id db coll oid)))))
(deftest add-value-to-an-existing-array-using-$addToSet-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$addToSet modifier appends value to field unless it is already there"]
(mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mc/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mc/find-map-by-id db coll oid)))))
(deftest double-add-value-to-an-existing-array-using-$addToSet-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$addToSet modifier appends value to field unless it is already there"]
(mc/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mc/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(mc/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mc/find-map-by-id db coll oid)))))
;;
;; $pop
;;
(deftest pop-last-value-in-the-array-using-$pop-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$pop modifier removes last or first value in the array"]
(mc/insert db coll { :_id oid :title title :tags ["products" "apple" "reviews"] })
(mc/update db coll { :_id oid } { $pop { :tags 1 } })
(is (= { :_id oid :title title :tags ["products" "apple"] } (mc/find-map-by-id db coll oid)))))
(deftest unshift-first-value-in-the-array-using-$pop-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$pop modifier removes last or first value in the array"]
(mc/insert db coll { :_id oid :title title :tags ["products" "apple" "reviews"] })
(mc/update db coll { :_id oid } { $pop { :tags -1 } })
(is (= { :_id oid :title title :tags ["apple" "reviews"] } (mc/find-map-by-id db coll oid)))))
(deftest pop-last-values-from-multiple-arrays-using-$pop-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$pop modifier removes last or first value in the array"]
(mc/insert db coll { :_id oid :title title :tags ["products" "apple" "reviews"] :categories ["apple" "reviews" "drafts"] })
(mc/update db coll { :_id oid } { $pop { :tags 1 :categories 1 } })
(is (= { :_id oid :title title :tags ["products" "apple"] :categories ["apple" "reviews"] } (mc/find-map-by-id db coll oid)))))
;;
;; $pull
;;
(deftest remove-all-value-entries-from-array-using-$pull-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$pull modifier removes all value entries in the array"]
(mc/insert db coll { :_id oid :title title :measurements [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0] })
(mc/update db coll { :_id oid } { $pull { :measurements 1.2 } })
(is (= { :_id oid :title title :measurements [1.0 1.1 1.1 1.3 1.0] } (mc/find-map-by-id db coll oid)))))
(deftest remove-all-value-entries-from-array-using-$pull-modifier-based-on-a-condition
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$pull modifier removes all value entries in the array"]
(mc/insert db coll { :_id oid :title title :measurements [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0] })
(mc/update db coll { :_id oid } { $pull { :measurements { $gte 1.2 } } })
(is (= { :_id oid :title title :measurements [1.0 1.1 1.1 1.0] } (mc/find-map-by-id db coll oid)))))
;;
;; $pullAll
;;
(deftest remove-all-value-entries-from-array-using-$pullAll-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$pullAll modifier removes entries of multiple values in the array"]
(mc/insert db coll { :_id oid :title title :measurements [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0] })
(mc/update db coll { :_id oid } { $pullAll { :measurements [1.0 1.1 1.2] } })
(is (= { :_id oid :title title :measurements [1.3] } (mc/find-map-by-id db coll oid)))))
;;
;; $rename
;;
(deftest rename-a-single-field-using-$rename-modifier
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
title "$rename renames fields"
v [1.0 1.2 1.2 1.2 1.1 1.1 1.2 1.3 1.0]]
(mc/insert db coll { :_id oid :title title :measurements v })
(mc/update db coll { :_id oid } { $rename { :measurements "results" } })
(is (= { :_id oid :title title :results v } (mc/find-map-by-id db coll oid)))))
;;
;; find-and-modify
;;
(deftest find-and-modify-a-single-document
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
doc {:_id oid :name "Sophie Bangs" :level 42}
conditions {:name "Sophie Bangs"}
update {$inc {:level 1}}]
(mc/insert db coll doc)
(let [res (mc/find-and-modify db 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 [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
doc {:_id oid :name "Sophie Bangs" :level 42}
conditions {:name "Sophie Bangs"}]
(mc/insert db coll doc)
(let [res (mc/find-and-modify db coll conditions {} :remove true)]
(is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 42}))
(is (empty? (mc/find-maps db coll conditions))))))
(deftest find-and-modify-upsert-a-document
(testing "case 1"
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
doc {:_id oid :name "Sophie Bangs" :level 42}]
(let [res (mc/find-and-modify db coll doc doc :upsert true)]
(is (empty? res))
(is (select-keys (mc/find-map-by-id db coll oid) [:name :level]) (dissoc doc :_id)))))
(testing "case 2"
(let [db (mg/get-db "altdb")
coll "docs"
query {:name "Sophie Bangs"}
doc (merge query {:level 42})]
(let [res (mc/find-and-modify db coll query doc :upsert true :return-new true)]
(is (:_id res))
(is (select-keys (mc/find-map-by-id db coll (:_id res)) [:name :level]) doc)))))
(deftest find-and-modify-after-sort
(let [db (mg/get-db "altdb")
coll "docs"
oid (ObjectId.)
oid2 (ObjectId.)
doc {:name "Sophie Bangs"}
doc1 (assoc doc :_id oid :level 42)
doc2 (assoc doc :_id oid2 :level 0)]
(mc/insert-batch db coll [doc1 doc2])
(let [res (mc/find-and-modify db coll doc {$inc {:level 1}} :sort {:level -1})]
(is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 42})))))

View file

@ -1,133 +0,0 @@
(ns monger.test.multi.collection-test
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject MapReduceOutput MapReduceCommand MapReduceCommand$OutputType]
org.bson.types.ObjectId
java.util.Date)
(:require [monger.core :as mg]
[monger.multi.collection :as mc]
[monger.result :as mgres]
[monger.test.helper :as helper]
[clojure.test :refer :all]
[monger.operators :refer :all]
[monger.test.fixtures :refer :all]))
(helper/connect!)
(def db (mg/get-db "altdb"))
(defn purge-altdb
[f]
(mc/remove db "things")
(mc/remove db "libraries")
(f))
(use-fixtures :each purge-altdb)
(deftest get-collection-size
(let [db (mg/get-db "altdb")
collection "things"]
(is (= 0 (mc/count db collection)))
(mc/insert-batch db collection [{:language "Clojure" :name "langohr"}
{:language "Clojure" :name "monger"}
{:language "Clojure" :name "incanter"}
{:language "Scala" :name "akka"}])
(is (= 4 (mc/count db collection)))
(is (mc/any? db collection))
(is (= 3 (mc/count db collection {:language "Clojure"})))
(is (mc/any? db collection {:language "Clojure"}))
(is (= 1 (mc/count db collection {:language "Scala" })))
(is (mc/any? db collection {:language "Scala"}))
(is (= 0 (mc/count db collection {:language "Python" })))
(is (not (mc/any? db collection {:language "Python"})))))
(deftest remove-all-documents-from-collection
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{:language "Clojure" :name "monger"}
{:language "Clojure" :name "langohr"}
{:language "Clojure" :name "incanter"}
{:language "Scala" :name "akka"}])
(is (= 4 (mc/count db collection)))
(mc/remove db collection)
(is (= 0 (mc/count db collection)))))
(deftest remove-some-documents-from-collection
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{:language "Clojure" :name "monger"}
{:language "Clojure" :name "langohr"}
{:language "Clojure" :name "incanter"}
{:language "Scala" :name "akka"}])
(is (= 4 (mc/count db collection)))
(mc/remove db collection {:language "Clojure"})
(is (= 1 (mc/count db collection)))))
(deftest remove-a-single-document-from-collection
(let [db (mg/get-db "altdb")
collection "libraries"
oid (ObjectId.)]
(mc/insert-batch db collection [{:language "Clojure" :name "monger" :_id oid}])
(mc/remove-by-id db collection oid)
(is (= 0 (mc/count db collection)))
(is (nil? (mc/find-by-id db collection oid)))))
(deftest checking-for-collection-existence-when-it-does-not-exist
(let [db (mg/get-db "altdb")
collection "widgets"]
(mc/drop db collection)
(is (false? (mc/exists? db collection)))))
(deftest checking-for-collection-existence-when-it-does-exist
(let [db (mg/get-db "altdb")
collection "widgets"]
(mc/drop db collection)
(mc/insert-batch db collection [{:name "widget1"}
{:name "widget2"}])
(is (mc/exists? db collection))
(mc/drop db collection)
(is (false? (mc/exists? db collection)))
(mc/create db "widgets" {:capped true :size 100000 :max 10})
(is (mc/exists? db collection))
(mc/rename db collection "gadgets")
(is (not (mc/exists? db collection)))
(is (mc/exists? db "gadgets"))
(mc/drop db "gadgets")))
(deftest test-any-on-empty-collection
(let [db (mg/get-db "altdb")
collection "things"]
(is (not (mc/any? db collection)))))
(deftest test-any-on-non-empty-collection
(let [db (mg/get-db "altdb")
collection "things"
_ (mc/insert db collection {:language "Clojure" :name "langohr"})]
(is (mc/any? db "things"))
(is (mc/any? db "things" {:language "Clojure"}))))
(deftest test-empty-on-empty-collection
(let [db (mg/get-db "altdb")
collection "things"]
(is (mc/empty? db collection))
(is (mc/empty? db collection))))
(deftest test-empty-on-non-empty-collection
(let [db (mg/get-db "altdb")
collection "things"
_ (mc/insert db collection {:language "Clojure" :name "langohr"})]
(is (not (mc/empty? db "things")))))
(deftest test-distinct-values
(let [db (mg/get-db "altdb")
collection "widgets"
batch [{:state "CA" :quantity 1 :price 199.00}
{:state "NY" :quantity 2 :price 199.00}
{:state "NY" :quantity 1 :price 299.00}
{:state "IL" :quantity 2 :price 11.50 }
{:state "CA" :quantity 2 :price 2.95 }
{:state "IL" :quantity 3 :price 5.50 }]]
(mc/insert-batch db collection batch)
(is (= ["CA" "IL" "NY"] (sort (mc/distinct db collection :state {}))))
(is (= ["CA" "NY"] (sort (mc/distinct db collection :state {:price {$gt 100.00}}))))))
(run-tests)

View file

@ -1,149 +0,0 @@
(ns monger.test.multi.find-test
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject DBRef]
org.bson.types.ObjectId
java.util.Date)
(:require [monger.core :as mg]
[monger.util :as mu]
[monger.multi.collection :as mc]
[monger.test.helper :as helper]
[monger.conversion :as mgcnv]
[clojure.test :refer :all]
[monger.operators :refer :all]
[monger.test.fixtures :refer :all]
[monger.conversion :refer :all]))
(helper/connect!)
(def db (mg/get-db "altdb"))
(defn purge-altdb
[f]
(mc/remove db "libraries")
(mc/remove db "docs")
(f))
(use-fixtures :each purge-altdb)
;;
;; find
;;
(deftest find-full-document-when-collection-is-empty
(let [db (mg/get-db "altdb")
collection "docs"
cursor (mc/find db collection)]
(is (empty? (iterator-seq cursor)))))
(deftest find-document-seq-when-collection-is-empty
(let [db (mg/get-db "altdb")
collection "docs"]
(is (empty? (mc/find-seq db collection)))))
(deftest find-multiple-documents-when-collection-is-empty
(let [db (mg/get-db "altdb")
collection "libraries"]
(is (empty? (mc/find db collection { :language "Scala" })))))
(deftest find-multiple-maps-when-collection-is-empty
(let [db (mg/get-db "altdb")
collection "libraries"]
(is (empty? (mc/find-maps db collection { :language "Scala" })))))
(deftest find-multiple-documents-by-regex
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Java", :name "nhibernate" }
{ :language "JavaScript", :name "sprout-core" }])
(is (= 2 (monger.core/count (mc/find db collection { :language #"Java*" }))))))
(deftest find-multiple-documents
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }])
(is (= 1 (monger.core/count (mc/find db collection { :language "Scala" }))))
(is (= 3 (.count (mc/find db collection { :language "Clojure" }))))
(is (empty? (mc/find db collection { :language "Java" })))))
(deftest find-document-specify-fields
(let [db (mg/get-db "altdb")
collection "libraries"
_ (mc/insert db collection { :language "Clojure", :name "monger" })
result (mc/find db 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
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }])
(doseq [doc (take 3 (map (fn [dbo]
(mgcnv/from-db-object dbo true))
(mc/find-seq db collection { :language "Clojure" })))]
(is (= "Clojure" (:language doc))))))
(deftest find-and-iterate-over-multiple-documents
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }])
(doseq [doc (take 3 (mc/find-maps db collection { :language "Clojure" }))]
(is (= "Clojure" (:language doc))))))
(deftest find-multiple-maps
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }])
(is (= 1 (count (mc/find-maps db collection { :language "Scala" }))))
(is (= 3 (count (mc/find-maps db collection { :language "Clojure" }))))
(is (empty? (mc/find-maps db collection { :language "Java" })))
(is (empty? (mc/find-maps db collection { :language "Java" } [:language :name])))))
(deftest find-multiple-partial-documents
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }])
(let [scala-libs (mc/find db collection { :language "Scala" } [:name])
clojure-libs (mc/find db collection { :language "Clojure"} [:language])]
(is (= 1 (.count scala-libs)))
(is (= 3 (.count clojure-libs)))
(doseq [i clojure-libs]
(let [doc (mgcnv/from-db-object i true)]
(is (= (:language doc) "Clojure"))))
(is (empty? (mc/find db collection { :language "Erlang" } [:name]))))))
(deftest finds-one-as-map
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }])
(let [res (mc/find-one-as-map db collection { :name "langohr" })]
(is (map? res))
(is (= "langohr" (:name res)))
(is (= "Clojure" (:language res))))
(is (= 2 (count (mc/find-one-as-map db collection { :name "langohr" } [:name]))))
(is (= "langohr" (get (mc/find-one-as-map db collection { :name "langohr" } [:name] false) "name")))))
(deftest find-and-modify
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }])))

View file

@ -1,60 +0,0 @@
(ns monger.test.multi.indexing-test
(:import org.bson.types.ObjectId
java.util.Date)
(:require [monger.core :as mg]
[monger.multi.collection :as mc]
[monger.test.helper :as helper]
monger.joda-time
[clojure.test :refer :all]
[monger.test.fixtures :refer :all]
[clj-time.core :refer [now secs ago from-now]]))
(helper/connect!)
(def db (mg/get-db "altdb"))
(defn purge-altdb
[f]
(mc/remove db "libraries")
(mc/remove db "recent_events")
(f))
(use-fixtures :each purge-altdb)
(deftest ^{:indexing true} test-creating-and-dropping-indexes
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/drop-indexes db collection)
(mc/create-index db collection { "language" 1 })
(is (= "language_1"
(:name (second (mc/indexes-on db collection)))))
(mc/drop-index db collection "language_1")
(mc/create-index db collection ["language"])
(mc/drop-index db collection "language_1")
(is (nil? (second (mc/indexes-on db collection))))
(mc/ensure-index db collection (array-map "language" 1) {:unique true})
(is (= "language_1"
(:name (second (mc/indexes-on db collection)))))
(mc/ensure-index db collection (array-map "language" 1))
(mc/ensure-index db collection (array-map "language" 1) { :unique true })
(mc/drop-indexes db collection)))
(deftest ^{:indexing true :edge-features true :time-consuming true} test-ttl-collections
(let [db (mg/get-db "altdb")
coll "recent_events"
ttl 30
sleep 120]
(mc/remove db coll)
(mc/ensure-index db coll (array-map :created-at 1) {:expireAfterSeconds ttl})
(dotimes [i 100]
(mc/insert db coll {:type "signup" :created-at (-> i secs ago) :i i}))
(dotimes [i 100]
(mc/insert db coll {:type "signup" :created-at (-> i secs from-now) :i i}))
(is (= 200 (mc/count db coll {:type "signup"})))
;; sleep for 65 seconds. MongoDB 2.1.2 seems to run TTLMonitor once per minute, according to
;; the log. MK.
(println (format "Now sleeping for %d seconds to test TTL collections!" sleep))
(Thread/sleep (* sleep 1000))
(println (format "Documents in the TTL collection: %d" (mc/count db coll {:type "signup"})))
(is (< (mc/count db coll {:type "signup"}) 100))
(mc/remove db coll)))

View file

@ -1,192 +0,0 @@
(ns monger.test.multi.inserting-test
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject DBRef]
org.bson.types.ObjectId
java.util.Date)
(:require [monger.core :as mg]
[monger.util :as mu]
[monger.multi.collection :as mc]
[monger.test.helper :as helper]
[clojure.test :refer :all]
[monger.operators :refer :all]
[monger.conversion :refer :all]
[monger.test.fixtures :refer :all]))
(helper/connect!)
(def db (mg/get-db "altdb"))
(defn purge-altdb
[f]
(mc/remove db "people")
(mc/remove db "widgets")
(f))
(use-fixtures :each purge-altdb)
;;
;; insert
;;
(deftest insert-a-basic-document-without-id-and-with-default-write-concern
(let [db (mg/get-db "altdb")
collection "people"
doc {:name "Joe" :age 30}]
(is (monger.result/ok? (mc/insert db "people" doc)))
(is (= 1 (mc/count db collection)))))
(deftest insert-a-basic-document-with-explicitly-passed-database-without-id-and-with-default-write-concern
(let [db (mg/get-db "altdb")
collection "people"
doc {:name "Joe" :age 30}]
(dotimes [n 5]
(is (monger.result/ok? (mc/insert db "people" doc WriteConcern/SAFE))))
(is (= 5 (mc/count db collection)))))
(deftest insert-a-basic-document-without-id-and-with-explicit-write-concern
(let [db (mg/get-db "altdb")
collection "people"
doc {:name "Joe" :age 30}]
(is (monger.result/ok? (mc/insert db "people" doc WriteConcern/SAFE)))
(is (= 1 (mc/count db collection)))))
(deftest insert-a-basic-db-object-without-id-and-with-default-write-concern
(let [db (mg/get-db "altdb")
collection "people"
doc (to-db-object {:name "Joe" :age 30})]
(is (nil? (.get ^DBObject doc "_id")))
(mc/insert db "people" doc)
(is (not (nil? (monger.util/get-id doc))))))
(deftest insert-a-map-with-id-and-with-default-write-concern
(let [db (mg/get-db "altdb")
collection "people"
id (ObjectId.)
doc {:name "Joe" :age 30 "_id" id}
result (mc/insert db "people" doc)]
(is (= id (monger.util/get-id doc)))))
(deftest insert-a-document-with-clojure-ratio-in-it
(let [db (mg/get-db "altdb")
collection "widgets"
id (ObjectId.)
doc {:ratio 11/2 "_id" id}
result (mc/insert db "widgets" doc)]
(is (= 5.5 (:ratio (mc/find-map-by-id db collection id))))))
(deftest insert-a-document-with-clojure-keyword-in-it
(let [db (mg/get-db "altdb")
collection "widgets"
id (ObjectId.)
doc {:keyword :kwd "_id" id}
result (mc/insert db "widgets" doc)]
(is (= (name :kwd) (:keyword (mc/find-map-by-id db collection id))))))
(deftest insert-a-document-with-clojure-keyword-in-a-set-in-it
(let [db (mg/get-db "altdb")
collection "widgets"
id (ObjectId.)
doc {:keyword1 {:keyword2 #{:kw1 :kw2}} "_id" id}
result (mc/insert db "widgets" doc)]
(is (= (sort ["kw1" "kw2"])
(sort (get-in (mc/find-map-by-id db collection id) [:keyword1 :keyword2]))))))
(defrecord Metrics
[rps eps])
(deftest insert-a-document-with-clojure-record-in-it
(let [db (mg/get-db "altdb")
collection "widgets"
id (ObjectId.)
doc {:record (Metrics. 10 20) "_id" id}
result (mc/insert db "widgets" doc)]
(is (= {:rps 10 :eps 20} (:record (mc/find-map-by-id db collection id))))))
(deftest test-insert-a-document-with-dbref
(let [db (mg/get-db "altdb")]
(mc/remove db "widgets")
(mc/remove db "owners")
(let [coll1 "widgets"
coll2 "owners"
oid (ObjectId.)
joe (mc/insert db "owners" {:name "Joe" :_id oid})
dbref (DBRef. (mg/current-db) coll2 oid)]
(mc/insert db coll1 {:type "pentagon" :owner dbref})
(let [fetched (mc/find-one-as-map db coll1 {:type "pentagon"})
fo (:owner fetched)]
(is (= {:_id oid :name "Joe"} (from-db-object @fo true)))))))
;;
;; insert-and-return
;;
(deftest insert-and-return-a-basic-document-without-id-and-with-default-write-concern
(let [db (mg/get-db "altdb")
collection "people"
doc {:name "Joe" :age 30}
result (mc/insert-and-return db :people doc)]
(is (= (:name doc)
(:name result)))
(is (= (:age doc)
(:age result)))
(is (:_id result))
(is (= 1 (mc/count db collection)))))
(deftest insert-and-return-a-basic-document-without-id-but-with-a-write-concern
(let [db (mg/get-db "altdb")
collection "people"
doc {:name "Joe" :age 30 :ratio 3/4}
result (mc/insert-and-return db "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 db collection)))))
(deftest insert-and-return-with-a-provided-id
(let [db (mg/get-db "altdb")
collection "people"
oid (ObjectId.)
doc {:name "Joe" :age 30 :_id oid}
result (mc/insert-and-return db :people doc)]
(is (= (:_id result) (:_id doc) oid))
(is (= 1 (mc/count db collection)))))
;;
;; insert-batch
;;
(deftest insert-a-batch-of-basic-documents-without-ids-and-with-default-write-concern
(let [db (mg/get-db "altdb")
collection "people"
docs [{:name "Joe" :age 30} {:name "Paul" :age 27}]]
(is (monger.result/ok? (mc/insert-batch db "people" docs)))
(is (= 2 (mc/count db collection)))))
(deftest insert-a-batch-of-basic-documents-without-ids-and-with-explicit-write-concern
(let [db (mg/get-db "altdb")
collection "people"
docs [{:name "Joe" :age 30} {:name "Paul" :age 27}]]
(is (monger.result/ok? (mc/insert-batch db "people" docs WriteConcern/NORMAL)))
(is (= 2 (mc/count db collection)))))
(deftest insert-a-batch-of-basic-documents-with-explicit-database-without-ids-and-with-explicit-write-concern
(let [db (mg/get-db "altdb")
collection "people"
docs [{:name "Joe" :age 30} {:name "Paul" :age 27}]]
(dotimes [n 44]
(is (monger.result/ok? (mc/insert-batch db "people" docs WriteConcern/NORMAL))))
(is (= 88 (mc/count db collection)))))
(deftest insert-a-batch-of-basic-documents-from-a-lazy-sequence
(let [db (mg/get-db "altdb")
collection "people"
numbers (range 0 1000)]
(is (monger.result/ok? (mc/insert-batch db "people" (map (fn [^long l]
{:n l})
numbers))))
(is (= (count numbers) (mc/count db collection)))))

View file

@ -1,186 +0,0 @@
(ns monger.test.multi.updating-test
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject]
org.bson.types.ObjectId
java.util.Date)
(:require [monger.core :as mg]
[monger core util]
[monger.multi.collection :as mc]
[monger.result :as mr]
[monger.test.helper :as helper]
[clojure.test :refer :all]
[monger.operators :refer :all]
[monger.test.fixtures :refer :all]
[monger.conversion :refer [to-db-object]]))
(helper/connect!)
(def db (mg/get-db "altdb"))
(defn purge-altdb
[f]
(mc/remove db "libraries")
(mc/remove db "people")
(mc/remove db "matches")
(f))
(use-fixtures :each purge-altdb)
;;
;; update, save
;;
(deftest ^{:updating true} update-document-by-id-without-upsert
(let [db (mg/get-db "altdb")
collection "libraries"
doc-id (monger.util/random-uuid)
date (Date.)
doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id }
modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }]
(mc/insert db collection doc)
(is (= (doc (mc/find-by-id db collection doc-id))))
(mc/update db collection { :_id doc-id } { :language "Erlang" })
(is (= (modified-doc (mc/find-by-id db collection doc-id))))))
(deftest ^{:updating true} update-document-by-id-without-upsert-using-update-by-id
(let [db (mg/get-db "altdb")
collection "libraries"
doc-id (monger.util/random-uuid)
date (Date.)
doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id }
modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }]
(mc/insert db collection doc)
(is (= (doc (mc/find-by-id db collection doc-id))))
(mc/update-by-id db collection doc-id { :language "Erlang" })
(is (= (modified-doc (mc/find-by-id db collection doc-id))))))
(deftest ^{:updating true} update-nested-document-fields-without-upsert-using-update-by-id
(let [db (mg/get-db "altdb")
collection "libraries"
doc-id (ObjectId.)
date (Date.)
doc { :created-at date :data-store "MongoDB" :language { :primary "Clojure" } :_id doc-id }
modified-doc { :created-at date :data-store "MongoDB" :language { :primary "Erlang" } :_id doc-id }]
(mc/insert db collection doc)
(is (= (doc (mc/find-by-id db collection doc-id))))
(mc/update-by-id db collection doc-id { $set { "language.primary" "Erlang" }})
(is (= (modified-doc (mc/find-by-id db collection doc-id))))))
(deftest ^{:updating true} update-multiple-documents
(let [db (mg/get-db "altdb")
collection "libraries"]
(mc/insert db collection { :language "Clojure", :name "monger" })
(mc/insert db collection { :language "Clojure", :name "langohr" })
(mc/insert db collection { :language "Clojure", :name "incanter" })
(mc/insert db collection { :language "Scala", :name "akka" })
(is (= 3 (mc/count db collection { :language "Clojure" })))
(is (= 1 (mc/count db collection { :language "Scala" })))
(is (= 0 (mc/count db collection { :language "Python" })))
(mc/update db collection { :language "Clojure" } { $set { :language "Python" } } :multi true)
(is (= 0 (mc/count db collection { :language "Clojure" })))
(is (= 1 (mc/count db collection { :language "Scala" })))
(is (= 3 (mc/count db collection { :language "Python" })))))
(deftest ^{:updating true} save-a-new-document
(let [db (mg/get-db "altdb")
collection "people"
document {:name "Joe" :age 30}]
(is (mr/ok? (mc/save db "people" document)))
(is (= 1 (mc/count db collection)))))
(deftest ^{:updating true} save-and-return-a-new-document
(let [db (mg/get-db "altdb")
collection "people"
document {:name "Joe" :age 30}
returned (mc/save-and-return db "people" document)]
(is (:_id returned))
(is (= document (dissoc returned :_id)))
(is (= 1 (mc/count db collection)))))
(deftest ^{:updating true} save-a-new-basic-db-object
(let [db (mg/get-db "altdb")
collection "people"
doc (to-db-object {:name "Joe" :age 30})]
(is (nil? (monger.util/get-id doc)))
(mc/save db "people" doc WriteConcern/SAFE)
(is (not (nil? (monger.util/get-id doc))))))
(deftest ^{:updating true} update-an-existing-document-using-save
(let [db (mg/get-db "altdb")
collection "people"
doc-id "people-1"
document { :_id doc-id, :name "Joe", :age 30 }]
(is (mr/ok? (mc/insert db "people" document)))
(is (= 1 (mc/count db collection)))
(mc/save db collection { :_id doc-id, :name "Alan", :age 40 })
(is (= 1 (mc/count db collection { :name "Alan", :age 40 })))))
(deftest ^{:updating true} update-an-existing-document-using-save-and-return
(let [db (mg/get-db "altdb")
collection "people"
document (mc/insert-and-return db "people" {:name "Joe" :age 30})
doc-id (:_id document)
updated (mc/save-and-return db collection {:_id doc-id :name "Alan" :age 40})]
(is (= {:_id doc-id :name "Alan" :age 40} updated))
(is (= 1 (mc/count db collection)))
(is (= 1 (mc/count db collection {:name "Alan" :age 40})))))
(deftest ^{:updating true} set-an-attribute-on-existing-document-using-update
(let [db (mg/get-db "altdb")
collection "people"
doc-id (monger.util/object-id)
document { :_id doc-id, :name "Joe", :age 30 }]
(is (mr/ok? (mc/insert db "people" document)))
(is (= 1 (mc/count db collection)))
(is (= 0 (mc/count db collection { :has_kids true })))
(mc/update db collection { :_id doc-id } { $set { :has_kids true } })
(is (= 1 (mc/count db collection { :has_kids true })))))
(deftest ^{:updating true} increment-multiple-fields-using-exists-operator-and-update
(let [db (mg/get-db "altdb")
collection "matches"
doc-id (monger.util/object-id)
document { :_id doc-id :abc 0 :def 10 }]
(mc/remove db collection)
(is (mr/ok? (mc/insert db collection document)))
(is (= 1 (mc/count db collection {:abc {$exists true} :def {$exists true}})))
(mc/update db collection {:abc {$exists true} :def {$exists true}} {$inc {:abc 1 :def 0}})
(is (= 1 (mc/count db collection { :abc 1 })))))
(deftest ^{:updating true} upsert-a-document-using-update
(let [db (mg/get-db "altdb")
collection "libraries"
doc-id (monger.util/random-uuid)
date (Date.)
doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id }
modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }]
(is (not (mr/updated-existing? (mc/update db collection { :language "Clojure" } doc :upsert true))))
(is (= 1 (mc/count db collection)))
(is (mr/updated-existing? (mc/update db collection { :language "Clojure" } modified-doc :multi false :upsert true)))
(is (= 1 (mc/count db collection)))
(is (= (modified-doc (mc/find-by-id db collection doc-id))))
(mc/remove db collection)))
(deftest ^{:updating true} upsert-a-document-using-upsert
(let [db (mg/get-db "altdb")
collection "libraries"
doc-id (monger.util/random-uuid)
date (Date.)
doc {:created-at date :data-store "MongoDB" :language "Clojure" :_id doc-id}
modified-doc {:created-at date :data-store "MongoDB" :language "Erlang" :_id doc-id}]
(mc/remove db collection)
(is (not (mr/updated-existing? (mc/upsert db collection {:language "Clojure"} doc))))
(is (= 1 (mc/count db collection)))
(is (mr/updated-existing? (mc/upsert db collection {:language "Clojure"} modified-doc :multi false)))
(is (= 1 (mc/count db collection)))
(is (= (modified-doc (mc/find-by-id db collection doc-id))))
(mc/remove db collection)))

View file

@ -1,109 +1,110 @@
(ns monger.test.query-operators-test (ns monger.test.query-operators-test
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject MapReduceOutput MapReduceCommand MapReduceCommand$OutputType] (:require [monger.core :as mg]
org.bson.types.ObjectId [monger.collection :as mc]
java.util.Date)
(:require [monger core util]
[clojure stacktrace]
[monger.collection :as mgcol]
[monger.result :as mgres]
[monger.conversion :as mgcnv]
[monger.js :as js] [monger.js :as js]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]))
[monger.test.fixtures :refer :all]))
(monger.core/connect!) ;; (use-fixtures :each purge-people purge-docs purge-things purge-libraries)
(monger.core/set-db! (monger.core/get-db "monger-test"))
(use-fixtures :each purge-people purge-docs purge-things purge-libraries) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(defn purge-collections
[f]
(mc/remove db "people")
(mc/remove db "libraries")
(f)
(mc/remove db "people")
(mc/remove db "libraries"))
;; (use-fixtures :each purge-collections)
;; $gt, $gte, $lt, lte
;;
(deftest find-with-conditional-operators-comparison ;;
;; $gt, $gte, $lt, lte
;;
(deftest find-with-conditional-operators-comparison
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{:language "Clojure" :name "monger" :users 1} (mc/insert-batch db collection [{:language "Clojure" :name "monger" :users 1}
{:language "Clojure" :name "langohr" :users 5} {:language "Clojure" :name "langohr" :users 5}
{:language "Clojure" :name "incanter" :users 15} {:language "Clojure" :name "incanter" :users 15}
{:language "Scala" :name "akka" :users 150}]) {:language "Scala" :name "akka" :users 150}])
(are [a b] (= a (.count (mgcol/find collection b))) (are [a b] (= a (.count (mc/find db collection b)))
2 {:users {$gt 10}} 2 {:users {$gt 10}}
3 {:users {$gte 5}} 3 {:users {$gte 5}}
2 {:users {$lt 10}} 2 {:users {$lt 10}}
2 {:users {$lte 5}} 2 {:users {$lte 5}}
1 {:users {$gt 10 $lt 150}}))) 1 {:users {$gt 10 $lt 150}})))
;; ;;
;; $ne ;; $ne
;; ;;
(deftest find-with-and-or-operators (deftest find-with-and-or-operators
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{:language "Ruby" :name "mongoid" :users 1} (mc/insert-batch db collection [{:language "Ruby" :name "mongoid" :users 1}
{:language "Clojure" :name "langohr" :users 5} {:language "Clojure" :name "langohr" :users 5}
{:language "Clojure" :name "incanter" :users 15} {:language "Clojure" :name "incanter" :users 15}
{:language "Scala" :name "akka" :users 150}]) {:language "Scala" :name "akka" :users 150}])
(is (= 2 (.count (mgcol/find collection {$ne {:language "Clojure"}})))))) (is (= 2 (.count (mc/find db collection {$ne {:language "Clojure"}}))))))
;; ;;
;; $and, $or, $nor ;; $and, $or, $nor
;; ;;
(deftest find-with-and-or-operators (deftest find-with-and-or-operators
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{:language "Ruby" :name "mongoid" :users 1} (mc/insert-batch db collection [{:language "Ruby" :name "mongoid" :users 1}
{:language "Clojure" :name "langohr" :users 5} {:language "Clojure" :name "langohr" :users 5}
{:language "Clojure" :name "incanter" :users 15} {:language "Clojure" :name "incanter" :users 15}
{:language "Scala" :name "akka" :users 150}]) {:language "Scala" :name "akka" :users 150}])
(is (= 1 (.count (mgcol/find collection {$and [{:language "Clojure"} (is (= 1 (.count (mc/find db collection {$and [{:language "Clojure"}
{:users {$gt 10}}]})))) {:users {$gt 10}}]}))))
(is (= 3 (.count (mgcol/find collection {$or [{:language "Clojure"} (is (= 3 (.count (mc/find db collection {$or [{:language "Clojure"}
{:users {$gt 10}} ]})))) {:users {$gt 10}} ]}))))
(is (= 1 (.count (mgcol/find collection {$nor [{:language "Clojure"} (is (= 1 (.count (mc/find db collection {$nor [{:language "Clojure"}
{:users {$gt 10}} ]})))))) {:users {$gt 10}} ]}))))))
;; ;;
;; $all, $in, $nin ;; $all, $in, $nin
;; ;;
(deftest find-on-embedded-arrays (deftest find-on-embedded-arrays
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{:language "Clojure" :tags [ "functional" ]} (mc/insert-batch db collection [{:language "Clojure" :tags [ "functional" ]}
{:language "Scala" :tags [ "functional" "object-oriented" ]} {:language "Scala" :tags [ "functional" "object-oriented" ]}
{:language "Ruby" :tags [ "object-oriented" "dynamic" ]}]) {:language "Ruby" :tags [ "object-oriented" "dynamic" ]}])
(is (= "Scala" (:language (first (mgcol/find-maps collection {:tags {$all [ "functional" "object-oriented" ]}} ))))) (is (= "Scala" (:language (first (mc/find-maps db collection {:tags {$all [ "functional" "object-oriented" ]}} )))))
(is (= 3 (.count (mgcol/find-maps collection {:tags {$in [ "functional" "object-oriented" ]}} )))) (is (= 3 (.count (mc/find-maps db collection {:tags {$in [ "functional" "object-oriented" ]}} ))))
(is (= 2 (.count (mgcol/find-maps collection {:language {$in [ "Scala" "Ruby" ]}} )))) (is (= 2 (.count (mc/find-maps db collection {:language {$in [ "Scala" "Ruby" ]}} ))))
(is (= 1 (.count (mgcol/find-maps collection {:tags {$nin [ "dynamic" "object-oriented" ]}} )))) (is (= 1 (.count (mc/find-maps db collection {:tags {$nin [ "dynamic" "object-oriented" ]}} ))))
(is (= 3 (.count (mgcol/find-maps collection {:language {$nin [ "C#" ]}} )))))) (is (= 3 (.count (mc/find-maps db collection {:language {$nin [ "C#" ]}} ))))))
(deftest find-with-conditional-operators-on-embedded-documents (deftest find-with-conditional-operators-on-embedded-documents
(let [collection "people"] (let [collection "people"]
(mgcol/insert-batch collection [{:name "Bob" :comments [{:text "Nice!" :rating 1} (mc/insert-batch db collection [{:name "Bob" :comments [{:text "Nice!" :rating 1}
{:text "Love it" :rating 4} {:text "Love it" :rating 4}
{:text "What?":rating -5} ]} {:text "What?":rating -5} ]}
{:name "Alice" :comments [{:text "Yeah" :rating 2} {:name "Alice" :comments [{:text "Yeah" :rating 2}
{:text "Doh" :rating 1} {:text "Doh" :rating 1}
{:text "Agreed" :rating 3}]}]) {:text "Agreed" :rating 3}]}])
(are [a b] (= a (.count (mgcol/find collection b))) (are [a b] (= a (.count (mc/find db collection b)))
1 {:comments {$elemMatch {:text "Nice!" :rating {$gte 1}}}} 1 {:comments {$elemMatch {:text "Nice!" :rating {$gte 1}}}}
2 {"comments.rating" 1} 2 {"comments.rating" 1}
1 {"comments.rating" {$gt 3}}))) 1 {"comments.rating" {$gt 3}})))
(deftest find-with-regex-operator (deftest find-with-regex-operator
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{:language "Ruby" :name "Mongoid" :users 1} (mc/insert-batch db collection [{:language "Ruby" :name "Mongoid" :users 1}
{:language "Clojure" :name "Langohr" :users 5} {:language "Clojure" :name "Langohr" :users 5}
{:language "Clojure" :name "Incanter" :users 15} {:language "Clojure" :name "Incanter" :users 15}
{:language "Scala" :name "Akka" :users 150}]) {:language "Scala" :name "Akka" :users 150}])
(are [query results] (is (= results (.count (mgcol/find collection query)))) (are [query results] (is (= results (.count (mc/find db collection query))))
{:language {$regex "Clo.*"}} 2 {:language {$regex "Clo.*"}} 2
{:language {$regex "clo.*" $options "i"}} 2 {:language {$regex "clo.*" $options "i"}} 2
{:name {$regex "aK.*" $options "i"}} 1 {:name {$regex "aK.*" $options "i"}} 1
{:language {$regex ".*by"}} 1 {:language {$regex ".*by"}} 1
{:language {$regex ".*ala.*"}} 1))) {:language {$regex ".*ala.*"}} 1))))

View file

@ -1,59 +1,69 @@
(ns monger.test.querying-test (ns monger.test.querying-test
(:refer-clojure :exclude [select find sort]) (:refer-clojure :exclude [select find sort])
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject ReadPreference] (:import [com.mongodb WriteResult WriteConcern DBObject ReadPreference]
org.bson.types.ObjectId org.bson.types.ObjectId
java.util.Date) java.util.Date)
(:require [monger core util] (:require [monger.core :as mg]
[monger.collection :as mgcol] [monger.collection :as mc]
monger.joda-time
[monger.result :as mgres] [monger.result :as mgres]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.test.fixtures :refer :all]
[monger.conversion :refer :all] [monger.conversion :refer :all]
[monger.query :refer :all] [monger.query :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]
[clj-time.core :refer [date-time]])) [clj-time.core :refer [date-time]]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(use-fixtures :each purge-docs purge-things purge-locations (defn purge-collections
purge-querying-docs) [f]
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "locations")
(mc/remove db "querying_docs")
(f)
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "locations")
(mc/remove db "querying_docs"))
(use-fixtures :each purge-collections)
;; ;;
;; monger.collection/* finders ("low-level API") ;; monger.collection/* finders ("low-level API")
;; ;;
;; by ObjectId ;; by ObjectId
(deftest query-full-document-by-object-id (deftest query-full-document-by-object-id
(let [coll "querying_docs" (let [coll "querying_docs"
oid (ObjectId.) oid (ObjectId.)
doc { :_id oid :title "Introducing Monger" }] doc { :_id oid :title "Introducing Monger" }]
(mgcol/insert coll doc) (mc/insert db coll doc)
(is (= doc (mgcol/find-map-by-id coll oid))) (is (= doc (mc/find-map-by-id db coll oid)))
(is (= doc (mgcol/find-one-as-map coll { :_id oid }))))) (is (= doc (mc/find-one-as-map db coll { :_id oid })))))
;; exact match over string field ;; exact match over string field
(deftest query-full-document-using-exact-matching-over-string-field (deftest query-full-document-using-exact-matching-over-string-field
(let [coll "querying_docs" (let [coll "querying_docs"
doc { :title "monger" :language "Clojure" :_id (ObjectId.) }] doc { :title "monger" :language "Clojure" :_id (ObjectId.) }]
(mgcol/insert coll doc) (mc/insert db coll doc)
(is (= [doc] (mgcol/find-maps coll { :title "monger" }))) (is (= [doc] (mc/find-maps db coll { :title "monger" })))
(is (= doc (from-db-object (first (mgcol/find coll { :title "monger" })) true))))) (is (= doc (from-db-object (first (mc/find db coll { :title "monger" })) true)))))
;; exact match over string field with limit ;; exact match over string field with limit
(deftest query-full-document-using-exact-matching-over-string-with-field-with-limit (deftest query-full-document-using-exact-matching-over-string-with-field-with-limit
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :title "monger" :language "Clojure" :_id (ObjectId.) } doc1 { :title "monger" :language "Clojure" :_id (ObjectId.) }
doc2 { :title "langohr" :language "Clojure" :_id (ObjectId.) } doc2 { :title "langohr" :language "Clojure" :_id (ObjectId.) }
doc3 { :title "netty" :language "Java" :_id (ObjectId.) } doc3 { :title "netty" :language "Java" :_id (ObjectId.) }
_ (mgcol/insert-batch coll [doc1 doc2 doc3]) _ (mc/insert-batch db coll [doc1 doc2 doc3])
result (with-collection coll result (with-collection db coll
(find { :title "monger" }) (find { :title "monger" })
(fields [:title, :language, :_id]) (fields [:title, :language, :_id])
(skip 0) (skip 0)
@ -62,13 +72,13 @@
(is (= [doc1] result)))) (is (= [doc1] result))))
(deftest query-full-document-using-exact-matching-over-string-field-with-limit-and-offset (deftest query-full-document-using-exact-matching-over-string-field-with-limit-and-offset
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :title "lucene" :language "Java" :_id (ObjectId.) } doc1 { :title "lucene" :language "Java" :_id (ObjectId.) }
doc2 { :title "joda-time" :language "Java" :_id (ObjectId.) } doc2 { :title "joda-time" :language "Java" :_id (ObjectId.) }
doc3 { :title "netty" :language "Java" :_id (ObjectId.) } doc3 { :title "netty" :language "Java" :_id (ObjectId.) }
_ (mgcol/insert-batch coll [doc1 doc2 doc3]) _ (mc/insert-batch db coll [doc1 doc2 doc3])
result (with-collection coll result (with-collection db coll
(find { :language "Java" }) (find { :language "Java" })
(skip 1) (skip 1)
(limit 2) (limit 2)
@ -76,24 +86,24 @@
(is (= 2 (count result))) (is (= 2 (count result)))
(is (= [doc1 doc3] result)))) (is (= [doc1 doc3] result))))
(deftest query-with-sorting-on-multiple-fields (deftest query-with-sorting-on-multiple-fields
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :a 1 :b 2 :c 3 :text "Whatever" :_id (ObjectId.) } doc1 { :a 1 :b 2 :c 3 :text "Whatever" :_id (ObjectId.) }
doc2 { :a 1 :b 1 :c 4 :text "Blah " :_id (ObjectId.) } doc2 { :a 1 :b 1 :c 4 :text "Blah " :_id (ObjectId.) }
doc3 { :a 10 :b 3 :c 1 :text "Abc" :_id (ObjectId.) } doc3 { :a 10 :b 3 :c 1 :text "Abc" :_id (ObjectId.) }
doc4 { :a 10 :b 3 :c 3 :text "Abc" :_id (ObjectId.) } doc4 { :a 10 :b 3 :c 3 :text "Abc" :_id (ObjectId.) }
_ (mgcol/insert-batch coll [doc1 doc2 doc3 doc4]) _ (mc/insert-batch db coll [doc1 doc2 doc3 doc4])
result1 (with-collection coll result1 (with-collection db coll
(find {}) (find {})
(limit 2) (limit 2)
(fields [:a :b :c :text]) (fields [:a :b :c :text])
(sort (sorted-map :a 1 :b 1 :text -1))) (sort (sorted-map :a 1 :b 1 :text -1)))
result2 (with-collection coll result2 (with-collection db coll
(find {}) (find {})
(limit 2) (limit 2)
(fields [:a :b :c :text]) (fields [:a :b :c :text])
(sort (array-map :c 1 :text -1))) (sort (array-map :c 1 :text -1)))
result3 (with-collection coll result3 (with-collection db coll
(find {}) (find {})
(limit 2) (limit 2)
(fields [:a :b :c :text]) (fields [:a :b :c :text])
@ -103,68 +113,68 @@
(is (= [doc2 doc4] result3)))) (is (= [doc2 doc4] result3))))
;; < ($lt), <= ($lte), > ($gt), >= ($gte) ;; < ($lt), <= ($lte), > ($gt), >= ($gte)
(deftest query-using-dsl-and-$lt-operator-with-integers (deftest query-using-dsl-and-$lt-operator-with-integers
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :language "Clojure" :_id (ObjectId.) :inception_year 2006 } doc1 { :language "Clojure" :_id (ObjectId.) :inception_year 2006 }
doc2 { :language "Java" :_id (ObjectId.) :inception_year 1992 } doc2 { :language "Java" :_id (ObjectId.) :inception_year 1992 }
doc3 { :language "Scala" :_id (ObjectId.) :inception_year 2003 } doc3 { :language "Scala" :_id (ObjectId.) :inception_year 2003 }
_ (mgcol/insert-batch coll [doc1 doc2]) _ (mc/insert-batch db coll [doc1 doc2])
lt-result (with-collection "querying_docs" lt-result (with-collection db coll
(find { :inception_year { $lt 2000 } }) (find { :inception_year { $lt 2000 } })
(limit 2))] (limit 2))]
(is (= [doc2] (vec lt-result))))) (is (= [doc2] (vec lt-result)))))
(deftest query-using-dsl-and-$lt-operator-with-dates (deftest query-using-dsl-and-$lt-operator-with-dates
(let [coll "querying_docs" (let [coll "querying_docs"
;; these rely on monger.joda-time being loaded. MK. ;; these rely on monger.joda-time being loaded. MK.
doc1 { :language "Clojure" :_id (ObjectId.) :inception_year (date-time 2006 1 1) } doc1 { :language "Clojure" :_id (ObjectId.) :inception_year (date-time 2006 1 1) }
doc2 { :language "Java" :_id (ObjectId.) :inception_year (date-time 1992 1 2) } doc2 { :language "Java" :_id (ObjectId.) :inception_year (date-time 1992 1 2) }
doc3 { :language "Scala" :_id (ObjectId.) :inception_year (date-time 2003 3 3) } doc3 { :language "Scala" :_id (ObjectId.) :inception_year (date-time 2003 3 3) }
_ (mgcol/insert-batch coll [doc1 doc2]) _ (mc/insert-batch db coll [doc1 doc2])
lt-result (with-collection "querying_docs" lt-result (with-collection db coll
(find { :inception_year { $lt (date-time 2000 1 2) } }) (find { :inception_year { $lt (date-time 2000 1 2) } })
(limit 2))] (limit 2))]
(is (= (map :_id [doc2]) (is (= (map :_id [doc2])
(map :_id (vec lt-result)))))) (map :_id (vec lt-result))))))
(deftest query-using-both-$lte-and-$gte-operators-with-dates (deftest query-using-both-$lte-and-$gte-operators-with-dates
(let [coll "querying_docs" (let [coll "querying_docs"
;; these rely on monger.joda-time being loaded. MK. ;; these rely on monger.joda-time being loaded. MK.
doc1 { :language "Clojure" :_id (ObjectId.) :inception_year (date-time 2006 1 1) } doc1 { :language "Clojure" :_id (ObjectId.) :inception_year (date-time 2006 1 1) }
doc2 { :language "Java" :_id (ObjectId.) :inception_year (date-time 1992 1 2) } doc2 { :language "Java" :_id (ObjectId.) :inception_year (date-time 1992 1 2) }
doc3 { :language "Scala" :_id (ObjectId.) :inception_year (date-time 2003 3 3) } doc3 { :language "Scala" :_id (ObjectId.) :inception_year (date-time 2003 3 3) }
_ (mgcol/insert-batch coll [doc1 doc2 doc3]) _ (mc/insert-batch db coll [doc1 doc2 doc3])
lt-result (with-collection "querying_docs" lt-result (with-collection db coll
(find { :inception_year { $gt (date-time 2000 1 2) $lte (date-time 2007 2 2) } }) (find { :inception_year { $gt (date-time 2000 1 2) $lte (date-time 2007 2 2) } })
(sort { :inception_year 1 }))] (sort { :inception_year 1 }))]
(is (= (map :_id [doc3 doc1]) (is (= (map :_id [doc3 doc1])
(map :_id (vec lt-result)))))) (map :_id (vec lt-result))))))
(deftest query-using-$gt-$lt-$gte-$lte-operators-as-strings (deftest query-using-$gt-$lt-$gte-$lte-operators-as-strings
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :language "Clojure" :_id (ObjectId.) :inception_year 2006 } doc1 { :language "Clojure" :_id (ObjectId.) :inception_year 2006 }
doc2 { :language "Java" :_id (ObjectId.) :inception_year 1992 } doc2 { :language "Java" :_id (ObjectId.) :inception_year 1992 }
doc3 { :language "Scala" :_id (ObjectId.) :inception_year 2003 } doc3 { :language "Scala" :_id (ObjectId.) :inception_year 2003 }
_ (mgcol/insert-batch coll [doc1 doc2 doc3])] _ (mc/insert-batch db coll [doc1 doc2 doc3])]
(are [doc, result] (are [doc, result]
(= doc, result) (= doc, result)
(doc2 (with-collection coll (doc2 (with-collection db coll
(find { :inception_year { "$lt" 2000 } }))) (find { :inception_year { "$lt" 2000 } })))
(doc2 (with-collection coll (doc2 (with-collection db coll
(find { :inception_year { "$lte" 1992 } }))) (find { :inception_year { "$lte" 1992 } })))
(doc1 (with-collection coll (doc1 (with-collection db coll
(find { :inception_year { "$gt" 2002 } }) (find { :inception_year { "$gt" 2002 } })
(limit 1) (limit 1)
(sort { :inception_year -1 }))) (sort { :inception_year -1 })))
(doc1 (with-collection coll (doc1 (with-collection db coll
(find { :inception_year { "$gte" 2006 } })))))) (find { :inception_year { "$gte" 2006 } }))))))
(deftest query-using-$gt-$lt-$gte-$lte-operators-using-dsl-composition (deftest query-using-$gt-$lt-$gte-$lte-operators-using-dsl-composition
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :language "Clojure" :_id (ObjectId.) :inception_year 2006 } doc1 { :language "Clojure" :_id (ObjectId.) :inception_year 2006 }
doc2 { :language "Java" :_id (ObjectId.) :inception_year 1992 } doc2 { :language "Java" :_id (ObjectId.) :inception_year 1992 }
@ -172,25 +182,25 @@
srt (-> {} srt (-> {}
(limit 1) (limit 1)
(sort { :inception_year -1 })) (sort { :inception_year -1 }))
_ (mgcol/insert-batch coll [doc1 doc2 doc3])] _ (mc/insert-batch db coll [doc1 doc2 doc3])]
(is (= [doc1] (with-collection coll (is (= [doc1] (with-collection db coll
(find { :inception_year { "$gt" 2002 } }) (find { :inception_year { "$gt" 2002 } })
(merge srt)))))) (merge srt))))))
;; $all ;; $all
(deftest query-with-using-$all (deftest query-with-using-$all
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :_id (ObjectId.) :title "Clojure" :tags ["functional" "homoiconic" "syntax-oriented" "dsls" "concurrency features" "jvm"] } doc1 { :_id (ObjectId.) :title "Clojure" :tags ["functional" "homoiconic" "syntax-oriented" "dsls" "concurrency features" "jvm"] }
doc2 { :_id (ObjectId.) :title "Java" :tags ["object-oriented" "jvm"] } doc2 { :_id (ObjectId.) :title "Java" :tags ["object-oriented" "jvm"] }
doc3 { :_id (ObjectId.) :title "Scala" :tags ["functional" "object-oriented" "dsls" "concurrency features" "jvm"] } doc3 { :_id (ObjectId.) :title "Scala" :tags ["functional" "object-oriented" "dsls" "concurrency features" "jvm"] }
- (mgcol/insert-batch coll [doc1 doc2 doc3]) - (mc/insert-batch db coll [doc1 doc2 doc3])
result1 (with-collection coll result1 (with-collection db coll
(find { :tags { "$all" ["functional" "jvm" "homoiconic"] } })) (find { :tags { "$all" ["functional" "jvm" "homoiconic"] } }))
result2 (with-collection coll result2 (with-collection db coll
(find { :tags { "$all" ["functional" "native" "homoiconic"] } })) (find { :tags { "$all" ["functional" "native" "homoiconic"] } }))
result3 (with-collection coll result3 (with-collection db coll
(find { :tags { "$all" ["functional" "jvm" "dsls"] } }) (find { :tags { "$all" ["functional" "jvm" "dsls"] } })
(sort { :title 1 }))] (sort { :title 1 }))]
(is (= [doc1] result1)) (is (= [doc1] result1))
@ -199,52 +209,52 @@
(is (= doc1 (first result3))))) (is (= doc1 (first result3)))))
;; $exists ;; $exists
(deftest query-with-find-one-as-map-using-$exists (deftest query-with-find-one-as-map-using-$exists
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :_id (ObjectId.) :published-by "Jill The Blogger" :draft false :title "X announces another Y" } doc1 { :_id (ObjectId.) :published-by "Jill The Blogger" :draft false :title "X announces another Y" }
doc2 { :_id (ObjectId.) :draft true :title "Z announces a Y competitor" } doc2 { :_id (ObjectId.) :draft true :title "Z announces a Y competitor" }
_ (mgcol/insert-batch coll [doc1 doc2]) _ (mc/insert-batch db coll [doc1 doc2])
result1 (mgcol/find-one-as-map coll { :published-by { "$exists" true } }) result1 (mc/find-one-as-map db coll { :published-by { "$exists" true } })
result2 (mgcol/find-one-as-map coll { :published-by { "$exists" false } })] result2 (mc/find-one-as-map db coll { :published-by { "$exists" false } })]
(is (= doc1 result1)) (is (= doc1 result1))
(is (= doc2 result2)))) (is (= doc2 result2))))
;; $mod ;; $mod
(deftest query-with-find-one-as-map-using-$mod (deftest query-with-find-one-as-map-using-$mod
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :_id (ObjectId.) :counter 25 } doc1 { :_id (ObjectId.) :counter 25 }
doc2 { :_id (ObjectId.) :counter 32 } doc2 { :_id (ObjectId.) :counter 32 }
doc3 { :_id (ObjectId.) :counter 63 } doc3 { :_id (ObjectId.) :counter 63 }
_ (mgcol/insert-batch coll [doc1 doc2 doc3]) _ (mc/insert-batch db coll [doc1 doc2 doc3])
result1 (mgcol/find-one-as-map coll { :counter { "$mod" [10, 5] } }) result1 (mc/find-one-as-map db coll { :counter { "$mod" [10, 5] } })
result2 (mgcol/find-one-as-map coll { :counter { "$mod" [10, 2] } }) result2 (mc/find-one-as-map db coll { :counter { "$mod" [10, 2] } })
result3 (mgcol/find-one-as-map coll { :counter { "$mod" [11, 1] } })] result3 (mc/find-one-as-map db coll { :counter { "$mod" [11, 1] } })]
(is (= doc1 result1)) (is (= doc1 result1))
(is (= doc2 result2)) (is (= doc2 result2))
(is (empty? result3)))) (is (empty? result3))))
;; $ne ;; $ne
(deftest query-with-find-one-as-map-using-$ne (deftest query-with-find-one-as-map-using-$ne
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :_id (ObjectId.) :counter 25 } doc1 { :_id (ObjectId.) :counter 25 }
doc2 { :_id (ObjectId.) :counter 32 } doc2 { :_id (ObjectId.) :counter 32 }
_ (mgcol/insert-batch coll [doc1 doc2]) _ (mc/insert-batch db coll [doc1 doc2])
result1 (mgcol/find-one-as-map coll { :counter { "$ne" 25 } }) result1 (mc/find-one-as-map db coll { :counter { "$ne" 25 } })
result2 (mgcol/find-one-as-map coll { :counter { "$ne" 32 } })] result2 (mc/find-one-as-map db coll { :counter { "$ne" 32 } })]
(is (= doc2 result1)) (is (= doc2 result1))
(is (= doc1 result2)))) (is (= doc1 result2))))
;; ;;
;; monger.query DSL features ;; monger.query DSL features
;; ;;
;; pagination ;; pagination
(deftest query-using-pagination-dsl (deftest query-using-pagination-dsl
(let [coll "querying_docs" (let [coll "querying_docs"
doc1 { :_id (ObjectId.) :title "Clojure" :tags ["functional" "homoiconic" "syntax-oriented" "dsls" "concurrency features" "jvm"] } doc1 { :_id (ObjectId.) :title "Clojure" :tags ["functional" "homoiconic" "syntax-oriented" "dsls" "concurrency features" "jvm"] }
doc2 { :_id (ObjectId.) :title "Java" :tags ["object-oriented" "jvm"] } doc2 { :_id (ObjectId.) :title "Java" :tags ["object-oriented" "jvm"] }
@ -253,22 +263,22 @@
doc5 { :_id (ObjectId.) :title "Groovy" :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"] } doc6 { :_id (ObjectId.) :title "OCaml" :tags ["functional" "static" "dsls"] }
doc7 { :_id (ObjectId.) :title "Haskell" :tags ["functional" "static" "dsls" "concurrency features"] } doc7 { :_id (ObjectId.) :title "Haskell" :tags ["functional" "static" "dsls" "concurrency features"] }
- (mgcol/insert-batch coll [doc1 doc2 doc3 doc4 doc5 doc6 doc7]) - (mc/insert-batch db coll [doc1 doc2 doc3 doc4 doc5 doc6 doc7])
result1 (with-collection coll result1 (with-collection db coll
(find {}) (find {})
(paginate :page 1 :per-page 3) (paginate :page 1 :per-page 3)
(sort { :title 1 }) (sort { :title 1 })
(read-preference (ReadPreference/primary)) (read-preference (ReadPreference/primary))
(options com.mongodb.Bytes/QUERYOPTION_NOTIMEOUT)) (options com.mongodb.Bytes/QUERYOPTION_NOTIMEOUT))
result2 (with-collection coll result2 (with-collection db coll
(find {}) (find {})
(paginate :page 2 :per-page 3) (paginate :page 2 :per-page 3)
(sort { :title 1 })) (sort { :title 1 }))
result3 (with-collection coll result3 (with-collection db coll
(find {}) (find {})
(paginate :page 3 :per-page 3) (paginate :page 3 :per-page 3)
(sort { :title 1 })) (sort { :title 1 }))
result4 (with-collection coll result4 (with-collection db coll
(find {}) (find {})
(paginate :page 10 :per-page 3) (paginate :page 10 :per-page 3)
(sort { :title 1 }))] (sort { :title 1 }))]
@ -278,7 +288,7 @@
(is (empty? result4)))) (is (empty? result4))))
(deftest combined-querying-dsl-example1 (deftest combined-querying-dsl-example1
(let [coll "querying_docs" (let [coll "querying_docs"
ma-doc { :_id (ObjectId.) :name "Massachusetts" :iso "MA" :population 6547629 :joined_in 1788 :capital "Boston" } ma-doc { :_id (ObjectId.) :name "Massachusetts" :iso "MA" :population 6547629 :joined_in 1788 :capital "Boston" }
de-doc { :_id (ObjectId.) :name "Delaware" :iso "DE" :population 897934 :joined_in 1787 :capital "Dover" } de-doc { :_id (ObjectId.) :name "Delaware" :iso "DE" :population 897934 :joined_in 1787 :capital "Dover" }
@ -287,14 +297,14 @@
tx-doc { :_id (ObjectId.) :name "Texas" :iso "TX" :population 25145561 :joined_in 1845 :capital "Austin" } tx-doc { :_id (ObjectId.) :name "Texas" :iso "TX" :population 25145561 :joined_in 1845 :capital "Austin" }
top3 (partial-query (limit 3)) top3 (partial-query (limit 3))
by-population-desc (partial-query (sort { :population -1 })) by-population-desc (partial-query (sort { :population -1 }))
_ (mgcol/insert-batch coll [ma-doc de-doc ny-doc ca-doc tx-doc]) _ (mc/insert-batch db coll [ma-doc de-doc ny-doc ca-doc tx-doc])
result (with-collection coll result (with-collection db coll
(find {}) (find {})
(merge top3) (merge top3)
(merge by-population-desc))] (merge by-population-desc))]
(is (= result [ca-doc tx-doc ny-doc])))) (is (= result [ca-doc tx-doc ny-doc]))))
(deftest combined-querying-dsl-example2 (deftest combined-querying-dsl-example2
(let [coll "querying_docs" (let [coll "querying_docs"
ma-doc { :_id (ObjectId.) :name "Massachusetts" :iso "MA" :population 6547629 :joined_in 1788 :capital "Boston" } ma-doc { :_id (ObjectId.) :name "Massachusetts" :iso "MA" :population 6547629 :joined_in 1788 :capital "Boston" }
de-doc { :_id (ObjectId.) :name "Delaware" :iso "DE" :population 897934 :joined_in 1787 :capital "Dover" } de-doc { :_id (ObjectId.) :name "Delaware" :iso "DE" :population 897934 :joined_in 1787 :capital "Dover" }
@ -303,8 +313,8 @@
tx-doc { :_id (ObjectId.) :name "Texas" :iso "TX" :population 25145561 :joined_in 1845 :capital "Austin" } tx-doc { :_id (ObjectId.) :name "Texas" :iso "TX" :population 25145561 :joined_in 1845 :capital "Austin" }
top3 (partial-query (limit 3)) top3 (partial-query (limit 3))
by-population-desc (partial-query (sort { :population -1 })) by-population-desc (partial-query (sort { :population -1 }))
_ (mgcol/insert-batch coll [ma-doc de-doc ny-doc ca-doc tx-doc]) _ (mc/insert-batch db coll [ma-doc de-doc ny-doc ca-doc tx-doc])
result (with-collection coll result (with-collection db coll
(find {}) (find {})
(merge top3) (merge top3)
(merge by-population-desc) (merge by-population-desc)
@ -312,4 +322,4 @@
;; documents have fields as strings, ;; documents have fields as strings,
;; not keywords ;; not keywords
(is (= (map #(% "name") result) (is (= (map #(% "name") result)
(map #(% :name) [ca-doc tx-doc ny-doc]))))) (map #(% :name) [ca-doc tx-doc ny-doc]))))))

View file

@ -1,22 +1,24 @@
(ns monger.test.ragtime-test (ns monger.test.ragtime-test
(:require [monger.core :as mg] (:require [monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[monger.test.helper :as helper]
monger.ragtime monger.ragtime
[clojure.test :refer :all] [ragtime.core :refer :all]
[monger.test.fixtures :refer [purge-migrations]] [clojure.test :refer :all]))
[ragtime.core :refer :all]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(defn purge-collections
[f]
(mc/remove db "meta.migrations")
(f)
(mc/remove db "meta.migrations"))
(use-fixtures :each purge-migrations) (use-fixtures :each purge-collections)
(when-not (get (System/getenv) "CI")
(when-not (get (System/getenv) "CI")
(deftest test-add-migration-id (deftest test-add-migration-id
(let [db (mg/get-db "monger-test") (let [coll "meta.migrations"
coll "meta.migrations"
key "1"] key "1"]
(mc/remove db coll {}) (mc/remove db coll {})
(is (not (mc/any? db coll {:_id key}))) (is (not (mc/any? db coll {:_id key})))
@ -27,8 +29,7 @@
(deftest test-remove-migration-id (deftest test-remove-migration-id
(let [db (mg/get-db "monger-test") (let [coll "meta.migrations"
coll "meta.migrations"
key "1"] key "1"]
(mc/remove db coll {}) (mc/remove db coll {})
(add-migration-id db key) (add-migration-id db key)
@ -39,8 +40,7 @@
(deftest test-migrations-ordering (deftest test-migrations-ordering
(let [db (mg/get-db "monger-test") (let [coll "meta.migrations"
coll "meta.migrations"
all-keys [ "9" "4" "7" "1" "5" "3" "6" "2" "8"]] all-keys [ "9" "4" "7" "1" "5" "3" "6" "2" "8"]]
(mc/remove db coll {}) (mc/remove db coll {})
@ -52,4 +52,4 @@
(is (some #{key} (applied-migration-ids db)))) (is (some #{key} (applied-migration-ids db))))
(testing "Applied migrations must come out in creation order" (testing "Applied migrations must come out in creation order"
(is (= all-keys (applied-migration-ids db))))))) (is (= all-keys (applied-migration-ids db))))))))

View file

@ -2,276 +2,283 @@
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject] (:import [com.mongodb WriteResult WriteConcern DBCursor DBObject]
org.bson.types.ObjectId org.bson.types.ObjectId
java.util.Date) java.util.Date)
(:require [monger core util] (:require [monger.core :as mg]
[monger.collection :as mgcol] [monger.collection :as mc]
[monger.util :as mu]
[monger.result :as mgres] [monger.result :as mgres]
[monger.conversion :as mgcnv] [monger.conversion :as mgcnv]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]))
[monger.test.fixtures :refer :all]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(use-fixtures :each (fn [f]
(mc/remove db "people")
(mc/remove db "docs")
(mc/remove db "regular_finders_docs")
(mc/remove db "things")
(mc/remove db "libraries")
(f)
(mc/remove db "people")
(mc/remove db "docs")
(mc/remove db "regular_finders_docs")
(mc/remove db "things")
(mc/remove db "libraries")))
(use-fixtures :each purge-people purge-docs purge-things purge-libraries ;;
purge-finder-docs) ;; find-one
;;
(deftest find-one-full-document-when-collection-is-empty
;;
;; find-one
;;
(deftest find-one-full-document-when-collection-is-empty
(let [collection "regular_finders_docs"] (let [collection "regular_finders_docs"]
(is (nil? (mgcol/find-one collection {}))))) (is (nil? (mc/find-one db collection {})))))
(deftest find-one-full-document-as-map-when-collection-is-empty (deftest find-one-full-document-as-map-when-collection-is-empty
(let [collection "regular_finders_docs"] (let [collection "regular_finders_docs"]
(mgcol/remove collection) (mc/remove db collection)
(is (nil? (mgcol/find-one-as-map collection {}))))) (is (nil? (mc/find-one-as-map db collection {})))))
(deftest find-one-full-document-when-collection-has-matches (deftest find-one-full-document-when-collection-has-matches
(let [collection "regular_finders_docs" (let [collection "regular_finders_docs"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }
_ (mgcol/insert collection doc) _ (mc/insert db collection doc)
found-one (mgcol/find-one collection { :language "Clojure" })] found-one (mc/find-one db collection { :language "Clojure" })]
(is found-one) (is found-one)
(is (= (:_id doc) (monger.util/get-id found-one))) (is (= (:_id doc) (mu/get-id found-one)))
(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 "regular_finders_docs" (let [collection "regular_finders_docs"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }] doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }]
(mgcol/insert collection doc) (mc/insert db collection doc)
(is (= doc (mgcol/find-one-as-map collection { :language "Clojure" }))))) (is (= doc (mc/find-one-as-map db collection { :language "Clojure" })))))
(deftest find-one-partial-document-when-collection-has-matches (deftest find-one-partial-document-when-collection-has-matches
(let [collection "regular_finders_docs" (let [collection "regular_finders_docs"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }
_ (mgcol/insert collection doc) _ (mc/insert db collection doc)
loaded (mgcol/find-one collection { :language "Clojure" } [:language])] loaded (mc/find-one db collection { :language "Clojure" } [:language])]
(is (nil? (.get ^DBObject loaded "data-store"))) (is (nil? (.get ^DBObject loaded "data-store")))
(is (= doc-id (monger.util/get-id loaded))) (is (= doc-id (mu/get-id loaded)))
(is (= "Clojure" (.get ^DBObject loaded "language"))))) (is (= "Clojure" (.get ^DBObject loaded "language")))))
(deftest find-one-partial-document-using-field-negation-when-collection-has-matches (deftest find-one-partial-document-using-field-negation-when-collection-has-matches
(let [collection "regular_finders_docs" (let [collection "regular_finders_docs"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }
_ (mgcol/insert collection doc) _ (mc/insert db collection doc)
^DBObject loaded (mgcol/find-one collection { :language "Clojure" } {:data-store 0 :_id 0})] ^DBObject loaded (mc/find-one db collection { :language "Clojure" } {:data-store 0 :_id 0})]
(is (nil? (.get loaded "data-store"))) (is (nil? (.get loaded "data-store")))
(is (nil? (.get loaded "_id"))) (is (nil? (.get loaded "_id")))
(is (nil? (monger.util/get-id loaded))) (is (nil? (mu/get-id loaded)))
(is (= "Clojure" (.get loaded "language"))))) (is (= "Clojure" (.get loaded "language")))))
(deftest find-one-partial-document-as-map-when-collection-has-matches (deftest find-one-partial-document-as-map-when-collection-has-matches
(let [collection "regular_finders_docs" (let [collection "regular_finders_docs"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }] doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }]
(mgcol/insert collection doc) (mc/insert db collection doc)
(is (= { :data-store "MongoDB", :_id doc-id } (mgcol/find-one-as-map collection { :language "Clojure" } [:data-store]))))) (is (= { :data-store "MongoDB", :_id doc-id }
(mc/find-one-as-map db collection { :language "Clojure" } [:data-store])))))
(deftest find-one-partial-document-as-map-when-collection-has-matches-with-keywordize (deftest find-one-partial-document-as-map-when-collection-has-matches-with-keywordize
(let [collection "regular_finders_docs" (let [collection "regular_finders_docs"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }
fields [:data-store] fields [:data-store]
_id (mgcol/insert collection doc) _id (mc/insert db collection doc)
loaded (mgcol/find-one-as-map collection { :language "Clojure" } fields true) loaded (mc/find-one-as-map db collection { :language "Clojure" } fields true)
] ]
(is (= { :data-store "MongoDB", :_id doc-id } loaded )))) (is (= { :data-store "MongoDB", :_id doc-id } loaded ))))
(deftest find-one-partial-document-as-map-when-collection-has-matches-with-keywordize-false (deftest find-one-partial-document-as-map-when-collection-has-matches-with-keywordize-false
(let [collection "regular_finders_docs" (let [collection "regular_finders_docs"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }
fields [:data-store] fields [:data-store]
_id (mgcol/insert collection doc) _id (mc/insert db collection doc)
loaded (mgcol/find-one-as-map collection { :language "Clojure" } fields false) loaded (mc/find-one-as-map db collection { :language "Clojure" } fields false)]
]
(is (= { "_id" doc-id, "data-store" "MongoDB" } loaded )))) (is (= { "_id" doc-id, "data-store" "MongoDB" } loaded ))))
;; ;;
;; find-by-id ;; find-by-id
;; ;;
(deftest find-full-document-by-string-id-when-that-document-does-not-exist (deftest find-full-document-by-string-id-when-that-document-does-not-exist
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid)] doc-id (mu/random-uuid)]
(is (nil? (mgcol/find-by-id collection doc-id))))) (is (nil? (mc/find-by-id db collection doc-id)))))
(deftest find-full-document-by-string-id-when-id-is-nil (deftest find-full-document-by-string-id-when-id-is-nil
(let [collection "libraries" (let [collection "libraries"
doc-id nil] doc-id nil]
(is (thrown? IllegalArgumentException (mgcol/find-by-id collection doc-id))))) (is (thrown? IllegalArgumentException (mc/find-by-id db collection doc-id)))))
(deftest find-full-document-by-object-id-when-that-document-does-not-exist (deftest find-full-document-by-object-id-when-that-document-does-not-exist
(let [collection "libraries" (let [collection "libraries"
doc-id (ObjectId.)] doc-id (ObjectId.)]
(is (nil? (mgcol/find-by-id collection doc-id))))) (is (nil? (mc/find-by-id db collection doc-id)))))
(deftest find-full-document-by-id-as-map-when-that-document-does-not-exist (deftest find-full-document-by-id-as-map-when-that-document-does-not-exist
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid)] doc-id (mu/random-uuid)]
(is (nil? (mgcol/find-map-by-id collection doc-id))))) (is (nil? (mc/find-map-by-id db collection doc-id)))))
(deftest find-full-document-by-id-as-map-when-id-is-nil (deftest find-full-document-by-id-as-map-when-id-is-nil
(let [collection "libraries" (let [collection "libraries"
doc-id nil] doc-id nil]
(is (thrown? IllegalArgumentException (is (thrown? IllegalArgumentException
(mgcol/find-map-by-id collection doc-id))))) (mc/find-map-by-id db collection doc-id)))))
(deftest find-full-document-by-string-id-when-document-does-exist (deftest find-full-document-by-string-id-when-document-does-exist
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }] doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }]
(mgcol/insert collection doc) (mc/insert db collection doc)
(is (= (doc (mgcol/find-by-id collection doc-id)))))) (is (= (doc (mc/find-by-id db collection doc-id))))))
(deftest find-full-document-by-object-id-when-document-does-exist (deftest find-full-document-by-object-id-when-document-does-exist
(let [collection "libraries" (let [collection "libraries"
doc-id (ObjectId.) doc-id (ObjectId.)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }] doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }]
(mgcol/insert collection doc) (mc/insert db collection doc)
(is (= (doc (mgcol/find-by-id collection doc-id)))))) (is (= (doc (mc/find-by-id db collection doc-id))))))
(deftest find-full-document-map-by-string-id-when-document-does-exist (deftest find-full-document-map-by-string-id-when-document-does-exist
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }] doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }]
(mgcol/insert collection doc) (mc/insert db collection doc)
(is (= (doc (mgcol/find-map-by-id collection doc-id)))))) (is (= (doc (mc/find-map-by-id db collection doc-id))))))
(deftest find-full-document-map-by-object-id-when-document-does-exist (deftest find-full-document-map-by-object-id-when-document-does-exist
(let [collection "libraries" (let [collection "libraries"
doc-id (ObjectId.) doc-id (ObjectId.)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }] doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }]
(mgcol/insert collection doc) (mc/insert db collection doc)
(is (= (doc (mgcol/find-map-by-id collection doc-id)))))) (is (= (doc (mc/find-map-by-id db collection doc-id))))))
(deftest find-partial-document-by-id-when-document-does-exist (deftest find-partial-document-by-id-when-document-does-exist
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }] doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }]
(mgcol/insert collection doc) (mc/insert db collection doc)
(is (= ({ :language "Clojure" } (mgcol/find-by-id collection doc-id [ :language ])))))) (is (= ({ :language "Clojure" }
(mc/find-by-id db collection doc-id [ :language ]))))))
(deftest find-partial-document-as-map-by-id-when-document-does-exist (deftest find-partial-document-as-map-by-id-when-document-does-exist
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
fields [:data-store] fields [:data-store]
doc { :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :data-store "MongoDB", :language "Clojure", :_id doc-id }
_ (mgcol/insert collection doc) _ (mc/insert db collection doc)
loaded (mgcol/find-map-by-id collection doc-id [ :language ])] loaded (mc/find-map-by-id db collection doc-id [ :language ])]
(is (= { :language "Clojure", :_id doc-id } loaded )) (is (= { :language "Clojure", :_id doc-id } loaded ))))
)
)
;; ;;
;; find ;; find
;; ;;
(deftest find-full-document-when-collection-is-empty (deftest find-full-document-when-collection-is-empty
(let [collection "regular_finders_docs" (let [collection "regular_finders_docs"
cursor (mgcol/find collection)] cursor (mc/find db collection)]
(is (empty? (iterator-seq cursor))))) (is (empty? (iterator-seq cursor)))))
(deftest find-document-seq-when-collection-is-empty (deftest find-document-seq-when-collection-is-empty
(let [collection "regular_finders_docs"] (let [collection "regular_finders_docs"]
(is (empty? (mgcol/find-seq collection))))) (is (empty? (mc/find-seq db 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? (mc/find db collection { :language "Scala" })))))
(deftest find-multiple-maps-when-collection-is-empty (deftest find-multiple-maps-when-collection-is-empty
(let [collection "libraries"] (let [collection "libraries"]
(is (empty? (mgcol/find-maps collection { :language "Scala" }))))) (is (empty? (mc/find-maps db collection { :language "Scala" })))))
(deftest find-multiple-documents-by-regex (deftest find-multiple-documents-by-regex
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{ :language "Clojure", :name "monger" } (mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Java", :name "nhibernate" } { :language "Java", :name "nhibernate" }
{ :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 (mc/find db 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" } (mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" } { :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" } { :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }]) { :language "Scala", :name "akka" }])
(is (= 1 (monger.core/count (mgcol/find collection { :language "Scala" })))) (is (= 1 (monger.core/count (mc/find db collection { :language "Scala" }))))
(is (= 3 (.count (mgcol/find collection { :language "Clojure" })))) (is (= 3 (.count (mc/find db collection { :language "Clojure" }))))
(is (empty? (mgcol/find collection { :language "Java" }))))) (is (empty? (mc/find db collection { :language "Java" })))))
(deftest find-document-specify-fields (deftest find-document-specify-fields
(let [collection "libraries" (let [collection "libraries"
_ (mgcol/insert collection { :language "Clojure", :name "monger" }) _ (mc/insert db collection { :language "Clojure", :name "monger" })
result (mgcol/find collection { :language "Clojure"} [:language])] result (mc/find db collection { :language "Clojure"} [:language])]
(is (= (seq [:_id :language]) (keys (mgcnv/from-db-object (.next result) true)))))) (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" } (mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" } { :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" } { :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }]) { :language "Scala", :name "akka" }])
(doseq [doc (take 3 (map (fn [dbo] (doseq [doc (take 3 (map (fn [dbo]
(mgcnv/from-db-object dbo true)) (mgcnv/from-db-object dbo true))
(mgcol/find-seq collection { :language "Clojure" })))] (mc/find-seq db collection { :language "Clojure" })))]
(is (= "Clojure" (:language doc)))))) (is (= "Clojure" (:language doc))))))
(deftest find-and-iterate-over-multiple-documents (deftest find-and-iterate-over-multiple-documents
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{ :language "Clojure", :name "monger" } (mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" } { :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" } { :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }]) { :language "Scala", :name "akka" }])
(doseq [doc (take 3 (mgcol/find-maps collection { :language "Clojure" }))] (doseq [doc (take 3 (mc/find-maps db collection { :language "Clojure" }))]
(is (= "Clojure" (:language doc)))))) (is (= "Clojure" (:language doc))))))
(deftest find-multiple-maps (deftest find-multiple-maps
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{ :language "Clojure", :name "monger" } (mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" } { :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" } { :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }]) { :language "Scala", :name "akka" }])
(is (= 1 (clojure.core/count (mgcol/find-maps collection { :language "Scala" })))) (is (= 1 (clojure.core/count (mc/find-maps db collection { :language "Scala" }))))
(is (= 3 (.count (mgcol/find-maps collection { :language "Clojure" })))) (is (= 3 (.count (mc/find-maps db collection { :language "Clojure" }))))
(is (empty? (mgcol/find-maps collection { :language "Java" }))) (is (empty? (mc/find-maps db collection { :language "Java" })))
(is (empty? (mgcol/find-maps monger.core/*mongodb-database* collection { :language "Java" } [:language :name]))))) (is (empty? (mc/find-maps db collection { :language "Java" } [:language :name])))))
(deftest find-multiple-partial-documents (deftest find-multiple-partial-documents
(let [collection "libraries"] (let [collection "libraries"]
(mgcol/insert-batch collection [{ :language "Clojure", :name "monger" } (mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" } { :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" } { :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }]) { :language "Scala", :name "akka" }])
(let [scala-libs (mgcol/find collection { :language "Scala" } [:name]) (let [scala-libs (mc/find db collection { :language "Scala" } [:name])
clojure-libs (mgcol/find collection { :language "Clojure"} [:language])] clojure-libs (mc/find db collection { :language "Clojure"} [:language])]
(is (= 1 (.count scala-libs))) (is (= 1 (.count scala-libs)))
(is (= 3 (.count clojure-libs))) (is (= 3 (.count clojure-libs)))
(doseq [i clojure-libs] (doseq [i clojure-libs]
(let [doc (mgcnv/from-db-object i true)] (let [doc (mgcnv/from-db-object i true)]
(is (= (:language doc) "Clojure")))) (is (= (:language doc) "Clojure"))))
(is (empty? (mgcol/find collection { :language "Erlang" } [:name])))))) (is (empty? (mc/find db collection { :language "Erlang" } [:name])))))))

View file

@ -1,16 +1,11 @@
(ns monger.test.result-test (ns monger.test.result-test
(:import [com.mongodb BasicDBObject WriteResult WriteConcern] java.util.Date) (:import [com.mongodb BasicDBObject WriteResult WriteConcern] java.util.Date)
(:require [monger core collection conversion] (:require [monger.core :as mg]
[monger.test.helper :as helper] [monger.collection :as mc]
monger.result
monger.util
[clojure.test :refer :all])) [clojure.test :refer :all]))
(helper/connect!)
;;
;; MongoCommandResult
;;
(deftest test-ok? (deftest test-ok?
(let [result-that-is-not-ok-1 (doto (BasicDBObject.) (.put "ok" 0)) (let [result-that-is-not-ok-1 (doto (BasicDBObject.) (.put "ok" 0))
result-that-is-not-ok-2 (doto (BasicDBObject.) (.put "ok" "false")) result-that-is-not-ok-2 (doto (BasicDBObject.) (.put "ok" "false"))
@ -41,14 +36,16 @@
(is (not (monger.result/updated-existing? input2))) (is (not (monger.result/updated-existing? input2)))
(is (not (monger.result/updated-existing? input3))))) (is (not (monger.result/updated-existing? input3)))))
(deftest test-updated-existing?-with-write-result (let [conn (mg/connect)
(monger.collection/remove "libraries") db (mg/get-db conn "monger-test")]
(deftest test-updated-existing?-with-write-result
(mc/remove db "libraries")
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid) doc-id (monger.util/random-uuid)
date (Date.) date (Date.)
doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id }
modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }] modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }]
(is (not (monger.result/updated-existing? (monger.collection/update collection { :language "Clojure" } doc :upsert true)))) (is (not (monger.result/updated-existing? (mc/update db collection { :language "Clojure" } doc {:upsert true}))))
(is (monger.result/updated-existing? (monger.collection/update collection { :language "Clojure" } doc :upsert true))) (is (monger.result/updated-existing? (mc/update db collection { :language "Clojure" } doc {:upsert true})))
(monger.result/updated-existing? (monger.collection/update collection { :language "Clojure" } modified-doc :multi false :upsert true)) (monger.result/updated-existing? (mc/update db collection { :language "Clojure" } modified-doc {:multi false :upsert true}))
(monger.collection/remove collection))) (mc/remove db collection))))

View file

@ -1,38 +1,29 @@
(ns monger.test.ring.clojure-session-store-test (ns monger.test.ring.clojure-session-store-test
(:require [monger core util] (:require [monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[ring.middleware.session.store :refer :all] [ring.middleware.session.store :refer :all]
[monger.ring.session-store :refer :all])) [monger.ring.session-store :refer :all]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(defn purge-sessions (defn purge-sessions
[f] [f]
(mc/remove "web_sessions") (mc/remove db "sessions")
(mc/remove "sessions")
(f) (f)
(mc/remove "web_sessions") (mc/remove db "sessions"))
(mc/remove "sessions"))
(use-fixtures :each purge-sessions) (use-fixtures :each purge-sessions)
(deftest test-reading-a-session-that-does-not-exist (deftest test-reading-a-session-that-does-not-exist
(let [store (session-store)] (let [store (session-store db "sessions")]
(is (= {} (read-session store "a-missing-key-1228277"))))) (is (= {} (read-session store "a-missing-key-1228277")))))
(deftest test-reading-a-session-that-does-not-exist-given-db (deftest test-reading-a-session-that-does-exist
(let [db (monger.core/get-db) (let [store (session-store db "sessions")
store (session-store db "sessions")]
(is (= {} (read-session store "a-missing-key-1228277")))))
(deftest test-reading-a-session-that-does-exist
(let [store (session-store)
sk (write-session store nil {:library "Monger"}) sk (write-session store nil {:library "Monger"})
m (read-session store sk)] m (read-session store sk)]
(is sk) (is sk)
@ -41,19 +32,8 @@
{:library "Monger"})))) {:library "Monger"}))))
(deftest test-reading-a-session-that-does-exist-given-db (deftest test-updating-a-session
(let [db (monger.core/get-db) (let [store (session-store db "sessions")
store (session-store db "sessions")
sk (write-session store nil {:library "Monger"})
m (read-session store sk)]
(is sk)
(is (and (:_id m)))
(is (= (dissoc m :_id)
{:library "Monger"}))))
(deftest test-updating-a-session
(let [store (session-store "sessions")
sk1 (write-session store nil {:library "Monger"}) sk1 (write-session store nil {:library "Monger"})
sk2 (write-session store sk1 {:library "Ring"}) sk2 (write-session store sk1 {:library "Ring"})
m (read-session store sk2)] m (read-session store sk2)]
@ -63,30 +43,8 @@
(is (= (dissoc m :_id) (is (= (dissoc m :_id)
{:library "Ring"})))) {:library "Ring"}))))
(deftest test-deleting-a-session
(deftest test-updating-a-session-given-db (let [store (session-store db "sessions")
(let [db (monger.core/get-db)
store (session-store db "sessions")
sk1 (write-session store nil {:library "Monger"})
sk2 (write-session store sk1 {:library "Ring"})
m (read-session store sk2)]
(is (and sk1 sk2))
(is (and (:_id m)))
(is (= sk1 sk2))
(is (= (dissoc m :_id)
{:library "Ring"}))))
(deftest test-deleting-a-session
(let [store (session-store "sessions")
sk (write-session store nil {:library "Monger"})] sk (write-session store nil {:library "Monger"})]
(is (nil? (delete-session store sk))) (is (nil? (delete-session store sk)))
(is (= {} (read-session store sk))))) (is (= {} (read-session store sk))))))
(deftest test-deleting-a-session
(let [db (monger.core/get-db)
store (session-store db "sessions")
sk (write-session store nil {:library "Monger"})]
(is (nil? (delete-session store sk)))
(is (= {} (read-session store sk)))))

View file

@ -1,38 +1,27 @@
(ns monger.test.ring.session-store-test (ns monger.test.ring.session-store-test
(:require [monger core util] (:require [monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[ring.middleware.session.store :refer :all] [ring.middleware.session.store :refer :all]
[monger.ring.session-store :refer :all])) [monger.ring.session-store :refer :all]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(defn purge-sessions (defn purge-sessions
[f] [f]
(mc/remove "web_sessions") (mc/remove db "sessions")
(mc/remove "sessions")
(f) (f)
(mc/remove "web_sessions") (mc/remove db "sessions"))
(mc/remove "sessions"))
(use-fixtures :each purge-sessions) (use-fixtures :each purge-sessions)
(deftest test-reading-a-session-that-does-not-exist
(deftest test-reading-a-session-that-does-not-exist (let [store (monger-store db "sessions")]
(let [store (monger-store)]
(is (= {} (read-session store "a-missing-key-1228277"))))) (is (= {} (read-session store "a-missing-key-1228277")))))
(deftest test-reading-a-session-that-does-exist
(deftest test-reading-a-session-that-does-not-exist-given-db (let [store (monger-store db "sessions")
(let [db (monger.core/get-db)
store (monger-store db "sessions")]
(is (= {} (read-session store "a-missing-key-1228277")))))
(deftest test-reading-a-session-that-does-exist
(let [store (monger-store)
sk (write-session store nil {:library "Monger"}) sk (write-session store nil {:library "Monger"})
m (read-session store sk)] m (read-session store sk)]
(is sk) (is sk)
@ -40,20 +29,8 @@
(is (= (dissoc m :_id :date) (is (= (dissoc m :_id :date)
{:library "Monger"})))) {:library "Monger"}))))
(deftest test-updating-a-session
(deftest test-reading-a-session-that-does-exist-given-db (let [store (monger-store db "sessions")
(let [db (monger.core/get-db)
store (monger-store db "sessions")
sk (write-session store nil {:library "Monger"})
m (read-session store sk)]
(is sk)
(is (and (:_id m) (:date m)))
(is (= (dissoc m :_id :date)
{:library "Monger"}))))
(deftest test-updating-a-session
(let [store (monger-store "sessions")
sk1 (write-session store nil {:library "Monger"}) sk1 (write-session store nil {:library "Monger"})
sk2 (write-session store sk1 {:library "Ring"}) sk2 (write-session store sk1 {:library "Ring"})
m (read-session store sk2)] m (read-session store sk2)]
@ -63,38 +40,15 @@
(is (= (dissoc m :_id :date) (is (= (dissoc m :_id :date)
{:library "Ring"})))) {:library "Ring"}))))
(deftest test-deleting-a-session
(deftest test-updating-a-session-given-db (let [store (monger-store db "sessions")
(let [db (monger.core/get-db)
store (monger-store db "sessions")
sk1 (write-session store nil {:library "Monger"})
sk2 (write-session store sk1 {:library "Ring"})
m (read-session store sk2)]
(is (and sk1 sk2))
(is (and (:_id m) (:date m)))
(is (= sk1 sk2))
(is (= (dissoc m :_id :date)
{:library "Ring"}))))
(deftest test-deleting-a-session
(let [store (monger-store "sessions")
sk (write-session store nil {:library "Monger"})] sk (write-session store nil {:library "Monger"})]
(is (nil? (delete-session store sk))) (is (nil? (delete-session store sk)))
(is (= {} (read-session store sk))))) (is (= {} (read-session store sk)))))
(deftest test-reader-extensions
(deftest test-deleting-a-session-given-db
(let [db (monger.core/get-db)
store (monger-store db "sessions")
sk (write-session store nil {:library "Monger"})]
(is (nil? (delete-session store sk)))
(is (= {} (read-session store sk)))))
(deftest test-reader-extensions
(let [d (java.util.Date.) (let [d (java.util.Date.)
oid (org.bson.types.ObjectId.)] oid (org.bson.types.ObjectId.)]
(binding [*print-dup* true] (binding [*print-dup* true]
(pr-str d) (pr-str d)
(pr-str oid)))) (pr-str oid)))))

View file

@ -1,42 +1,35 @@
(ns monger.test.stress-test (ns monger.test.stress-test
(:import [com.mongodb Mongo DB DBCollection WriteResult DBObject WriteConcern DBCursor] (:require [monger.core :as mg]
java.util.Date) [monger.collection :as mc]
(:require monger.core [monger.conversion :refer [to-db-object]]
[monger.test.helper :as helper] [clojure.test :refer :all])
[clojure.test :refer :all])) (:import [com.mongodb WriteConcern]
java.util.Date))
;; (let [conn (mg/connect)
;; Fixture functions db (mg/get-db conn "monger-test")]
;; (defn purge-collection
[coll f]
(defn purge-collection (mc/remove db coll)
[collection-name, f]
(monger.collection/remove collection-name)
(f) (f)
(monger.collection/remove collection-name)) (mc/remove db coll))
(defn purge-things-collection (defn purge-things-collection
[f] [f]
(purge-collection "things" f)) (purge-collection "things" f))
(use-fixtures :each purge-things-collection) (use-fixtures :each purge-things-collection)
(monger.core/set-default-write-concern! WriteConcern/NORMAL)
(deftest ^{:performance true} insert-large-batches-of-documents-without-object-ids
;; (doseq [n [10 100 1000 10000 20000]]
;; Tests
;;
(monger.core/set-default-write-concern! WriteConcern/NORMAL)
(deftest ^{:performance true} insert-large-batches-of-documents-without-object-ids
(doseq [n [1000 10000 100000]]
(let [collection "things" (let [collection "things"
docs (map (fn [i] docs (map (fn [i]
(monger.conversion/to-db-object { :title "Untitled" :created-at (Date.) :number i })) (to-db-object { :title "Untitled" :created-at (Date.) :number i }))
(take n (iterate inc 1)))] (take n (iterate inc 1)))]
(monger.collection/remove collection) (mc/remove db collection)
(println "Inserting " n " documents...") (println "Inserting " n " documents...")
(time (monger.collection/insert-batch collection docs)) (time (mc/insert-batch db collection docs))
(is (= n (monger.collection/count collection)))))) (is (= n (mc/count db collection)))))))

View file

@ -1,163 +1,169 @@
(ns monger.test.updating-test (ns monger.test.updating-test
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject] (:import [com.mongodb WriteResult WriteConcern DBObject]
org.bson.types.ObjectId org.bson.types.ObjectId
java.util.Date) java.util.Date)
(:require [monger core util] (:require [monger.core :as mg]
[monger.collection :as mc] [monger.collection :as mc]
[monger.util :as mu]
[monger.result :as mr] [monger.result :as mr]
[monger.test.helper :as helper]
[clojure.test :refer :all] [clojure.test :refer :all]
[monger.operators :refer :all] [monger.operators :refer :all]
[monger.test.fixtures :refer :all]
[monger.conversion :refer [to-db-object]])) [monger.conversion :refer [to-db-object]]))
(helper/connect!) (let [conn (mg/connect)
db (mg/get-db conn "monger-test")]
(defn purge-collections
[f]
(mc/remove db "people")
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "libraries")
(f)
(mc/remove db "people")
(mc/remove db "docs")
(mc/remove db "things")
(mc/remove db "libraries"))
(use-fixtures :each purge-people purge-docs purge-things purge-libraries) (use-fixtures :each purge-collections)
(deftest ^{:updating true} update-document-by-id-without-upsert
;;
;; update, save
;;
(deftest ^{:updating true} update-document-by-id-without-upsert
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
date (Date.) date (Date.)
doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id }
modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }] modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }]
(mc/insert collection doc) (mc/insert db collection doc)
(is (= (doc (mc/find-by-id collection doc-id)))) (is (= (doc (mc/find-by-id db collection doc-id))))
(mc/update collection { :_id doc-id } { :language "Erlang" }) (mc/update db collection { :_id doc-id } { :language "Erlang" })
(is (= (modified-doc (mc/find-by-id collection doc-id)))))) (is (= (modified-doc (mc/find-by-id db collection doc-id))))))
(deftest ^{:updating true} update-document-by-id-without-upsert-using-update-by-id (deftest ^{:updating true} update-document-by-id-without-upsert-using-update-by-id
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
date (Date.) date (Date.)
doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id }
modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }] modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }]
(mc/insert collection doc) (mc/insert db collection doc)
(is (= (doc (mc/find-by-id collection doc-id)))) (is (= (doc (mc/find-by-id db collection doc-id))))
(mc/update-by-id collection doc-id { :language "Erlang" }) (mc/update-by-id db collection doc-id { :language "Erlang" })
(is (= (modified-doc (mc/find-by-id collection doc-id)))))) (is (= (modified-doc (mc/find-by-id db collection doc-id))))))
(deftest ^{:updating true} update-nested-document-fields-without-upsert-using-update-by-id (deftest ^{:updating true} update-nested-document-fields-without-upsert-using-update-by-id
(let [collection "libraries" (let [collection "libraries"
doc-id (ObjectId.) doc-id (ObjectId.)
date (Date.) date (Date.)
doc { :created-at date :data-store "MongoDB" :language { :primary "Clojure" } :_id doc-id } doc { :created-at date :data-store "MongoDB" :language { :primary "Clojure" } :_id doc-id }
modified-doc { :created-at date :data-store "MongoDB" :language { :primary "Erlang" } :_id doc-id }] modified-doc { :created-at date :data-store "MongoDB" :language { :primary "Erlang" } :_id doc-id }]
(mc/insert collection doc) (mc/insert db collection doc)
(is (= (doc (mc/find-by-id collection doc-id)))) (is (= (doc (mc/find-by-id db collection doc-id))))
(mc/update-by-id collection doc-id { $set { "language.primary" "Erlang" }}) (mc/update-by-id db collection doc-id { $set { "language.primary" "Erlang" }})
(is (= (modified-doc (mc/find-by-id collection doc-id)))))) (is (= (modified-doc (mc/find-by-id db collection doc-id))))))
(deftest ^{:updating true} update-multiple-documents (deftest ^{:updating true} update-multiple-documents
(let [collection "libraries"] (let [collection "libraries"]
(mc/insert collection { :language "Clojure", :name "monger" }) (mc/insert-batch db collection [{ :language "Clojure", :name "monger" }
(mc/insert collection { :language "Clojure", :name "langohr" }) { :language "Clojure", :name "langohr" }
(mc/insert collection { :language "Clojure", :name "incanter" }) { :language "Clojure", :name "incanter" }
(mc/insert collection { :language "Scala", :name "akka" }) { :language "Scala", :name "akka" }])
(is (= 3 (mc/count collection { :language "Clojure" }))) (is (= 3 (mc/count db collection { :language "Clojure" })))
(is (= 1 (mc/count collection { :language "Scala" }))) (is (= 1 (mc/count db collection { :language "Scala" })))
(is (= 0 (mc/count collection { :language "Python" }))) (is (= 0 (mc/count db collection { :language "Python" })))
(mc/update collection { :language "Clojure" } { $set { :language "Python" } } :multi true) (mc/update db collection { :language "Clojure" } { $set { :language "Python" } } {:multi true})
(is (= 0 (mc/count collection { :language "Clojure" }))) (is (= 0 (mc/count db collection { :language "Clojure" })))
(is (= 1 (mc/count collection { :language "Scala" }))) (is (= 1 (mc/count db collection { :language "Scala" })))
(is (= 3 (mc/count collection { :language "Python" }))))) (is (= 3 (mc/count db collection { :language "Python" })))))
(deftest ^{:updating true} save-a-new-document (deftest ^{:updating true} save-a-new-document
(let [collection "people" (let [collection "people"
document {:name "Joe" :age 30}] document {:name "Joe" :age 30}]
(is (mr/ok? (mc/save "people" document))) (is (mr/ok? (mc/save db "people" document)))
(is (= 1 (mc/count collection))))) (is (= 1 (mc/count db collection)))))
(deftest ^{:updating true} save-and-return-a-new-document (deftest ^{:updating true} save-and-return-a-new-document
(let [collection "people" (let [collection "people"
document {:name "Joe" :age 30} document {:name "Joe" :age 30}
returned (mc/save-and-return "people" document)] returned (mc/save-and-return db "people" document)]
(is (:_id returned)) (is (:_id returned))
(is (= document (dissoc returned :_id))) (is (= document (dissoc returned :_id)))
(is (= 1 (mc/count collection))))) (is (= 1 (mc/count db collection)))))
(deftest ^{:updating true} save-a-new-basic-db-object (deftest ^{:updating true} save-a-new-basic-db-object
(let [collection "people" (let [collection "people"
doc (to-db-object {:name "Joe" :age 30})] doc (to-db-object {:name "Joe" :age 30})]
(is (nil? (monger.util/get-id doc))) (is (nil? (mu/get-id doc)))
(mc/save monger.core/*mongodb-database* "people" doc WriteConcern/SAFE) (mc/save db "people" doc WriteConcern/SAFE)
(is (not (nil? (monger.util/get-id doc)))))) (is (not (nil? (mu/get-id doc))))))
(deftest ^{:updating true} update-an-existing-document-using-save (deftest ^{:updating true} update-an-existing-document-using-save
(let [collection "people" (let [collection "people"
doc-id "people-1" doc-id "people-1"
document { :_id doc-id, :name "Joe", :age 30 }] document { :_id doc-id, :name "Joe", :age 30 }]
(is (mr/ok? (mc/insert "people" document))) (is (mr/ok? (mc/insert db collection document)))
(is (= 1 (mc/count collection))) (is (= 1 (mc/count db collection)))
(mc/save collection { :_id doc-id, :name "Alan", :age 40 }) (mc/save db collection { :_id doc-id, :name "Alan", :age 40 })
(is (= 1 (mc/count collection { :name "Alan", :age 40 }))))) (is (= 1 (mc/count db collection { :name "Alan", :age 40 })))))
(deftest ^{:updating true} update-an-existing-document-using-save-and-return (deftest ^{:updating true} update-an-existing-document-using-save-and-return
(let [collection "people" (let [collection "people"
document (mc/insert-and-return "people" {:name "Joe" :age 30}) document (mc/insert-and-return db collection {:name "Joe" :age 30})
doc-id (:_id document) doc-id (:_id document)
updated (mc/save-and-return collection {:_id doc-id :name "Alan" :age 40})] updated (mc/save-and-return db collection {:_id doc-id :name "Alan" :age 40})]
(is (= {:_id doc-id :name "Alan" :age 40} updated)) (is (= {:_id doc-id :name "Alan" :age 40} updated))
(is (= 1 (mc/count collection))) (is (= 1 (mc/count db collection)))
(is (= 1 (mc/count collection {:name "Alan" :age 40}))))) (is (= 1 (mc/count db collection {:name "Alan" :age 40})))))
(deftest ^{:updating true} set-an-attribute-on-existing-document-using-update (deftest ^{:updating true} set-an-attribute-on-existing-document-using-update
(let [collection "people" (let [collection "people"
doc-id (monger.util/object-id) doc-id (mu/object-id)
document { :_id doc-id, :name "Joe", :age 30 }] document { :_id doc-id, :name "Joe", :age 30 }]
(is (mr/ok? (mc/insert "people" document))) (is (mr/ok? (mc/insert db collection document)))
(is (= 1 (mc/count collection))) (is (= 1 (mc/count db collection)))
(is (= 0 (mc/count collection { :has_kids true }))) (is (= 0 (mc/count db collection { :has_kids true })))
(mc/update collection { :_id doc-id } { $set { :has_kids true } }) (mc/update db collection { :_id doc-id } { $set { :has_kids true } })
(is (= 1 (mc/count collection { :has_kids true }))))) (is (= 1 (mc/count db collection { :has_kids true })))))
(deftest ^{:updating true} increment-multiple-fields-using-exists-operator-and-update (deftest ^{:updating true} increment-multiple-fields-using-exists-operator-and-update
(let [collection "matches" (let [collection "matches"
doc-id (monger.util/object-id) doc-id (mu/object-id)
document { :_id doc-id :abc 0 :def 10 }] document { :_id doc-id :abc 0 :def 10 }]
(mc/remove collection) (mc/remove db collection)
(is (mr/ok? (mc/insert collection document))) (is (mr/ok? (mc/insert db collection document)))
(is (= 1 (mc/count collection {:abc {$exists true} :def {$exists true}}))) (is (= 1 (mc/count db collection {:abc {$exists true} :def {$exists true}})))
(mc/update collection {:abc {$exists true} :def {$exists true}} {$inc {:abc 1 :def 0}}) (mc/update db collection {:abc {$exists true} :def {$exists true}} {$inc {:abc 1 :def 0}})
(is (= 1 (mc/count collection { :abc 1 }))))) (is (= 1 (mc/count db collection { :abc 1 })))))
(deftest ^{:updating true} upsert-a-document-using-update (deftest ^{:updating true} upsert-a-document-using-update
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
date (Date.) date (Date.)
doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id } doc { :created-at date, :data-store "MongoDB", :language "Clojure", :_id doc-id }
modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }] modified-doc { :created-at date, :data-store "MongoDB", :language "Erlang", :_id doc-id }]
(is (not (mr/updated-existing? (mc/update collection { :language "Clojure" } doc :upsert true)))) (is (not (mr/updated-existing? (mc/update db collection { :language "Clojure" } doc {:upsert true}))))
(is (= 1 (mc/count collection))) (is (= 1 (mc/count db collection)))
(is (mr/updated-existing? (mc/update collection { :language "Clojure" } modified-doc :multi false :upsert true))) (is (mr/updated-existing? (mc/update db collection { :language "Clojure" } modified-doc {:multi false :upsert true})))
(is (= 1 (mc/count collection))) (is (= 1 (mc/count db collection)))
(is (= (modified-doc (mc/find-by-id collection doc-id)))) (is (= (modified-doc (mc/find-by-id db collection doc-id))))
(mc/remove collection))) (mc/remove db collection)))
(deftest ^{:updating true} upsert-a-document-using-upsert (deftest ^{:updating true} upsert-a-document-using-upsert
(let [collection "libraries" (let [collection "libraries"
doc-id (monger.util/random-uuid) doc-id (mu/random-uuid)
date (Date.) date (Date.)
doc {:created-at date :data-store "MongoDB" :language "Clojure" :_id doc-id} doc {:created-at date :data-store "MongoDB" :language "Clojure" :_id doc-id}
modified-doc {:created-at date :data-store "MongoDB" :language "Erlang" :_id doc-id}] modified-doc {:created-at date :data-store "MongoDB" :language "Erlang" :_id doc-id}]
(mc/remove collection) (mc/remove db collection)
(is (not (mr/updated-existing? (mc/upsert collection {:language "Clojure"} doc)))) (is (not (mr/updated-existing? (mc/upsert db collection {:language "Clojure"} doc))))
(is (= 1 (mc/count collection))) (is (= 1 (mc/count db collection)))
(is (mr/updated-existing? (mc/upsert collection {:language "Clojure"} modified-doc :multi false))) (is (mr/updated-existing? (mc/upsert db collection {:language "Clojure"} modified-doc {:multi false})))
(is (= 1 (mc/count collection))) (is (= 1 (mc/count db collection)))
(is (= (modified-doc (mc/find-by-id collection doc-id)))) (is (= (modified-doc (mc/find-by-id db collection doc-id))))
(mc/remove collection))) (mc/remove db collection))))