Merge pull request #55 from ebaxt/multi

Finished multi.collection
This commit is contained in:
Michael Klishin 2013-06-23 05:58:46 -07:00
commit c0f1112d34
7 changed files with 1255 additions and 6 deletions

View file

@ -4,7 +4,7 @@
Use these functions when you need to work with multiple databases or manage database Use these functions when you need to work with multiple databases or manage database
and connection lifecycle explicitly." and connection lifecycle explicitly."
(:refer-clojure :exclude [find remove count]) (:refer-clojure :exclude [find remove count empty? distinct drop])
(:import [com.mongodb Mongo DB DBCollection WriteResult DBObject WriteConcern DBCursor MapReduceCommand MapReduceCommand$OutputType] (:import [com.mongodb Mongo DB DBCollection WriteResult DBObject WriteConcern DBCursor MapReduceCommand MapReduceCommand$OutputType]
[java.util List Map] [java.util List Map]
[clojure.lang IPersistentMap ISeq] [clojure.lang IPersistentMap ISeq]
@ -60,11 +60,13 @@
;; ;;
;; monger.collection/find ;; monger.multi.collection/find
;; ;;
(defn ^DBCursor find (defn ^DBCursor find
"Like monger.collection/find but always takes a database as explicit argument" "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] ([^DB db ^String collection ^Map ref]
(.find (.getCollection db (name collection)) (.find (.getCollection db (name collection))
(to-db-object ref))) (to-db-object ref)))
@ -75,6 +77,9 @@
(defn find-maps (defn find-maps
"Like monger.collection/find-maps but always takes a database as explicit argument" "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] ([^DB db ^String collection ^Map ref]
(with-open [dbc (find db collection ref)] (with-open [dbc (find db collection ref)]
(map (fn [x] (from-db-object x true)) dbc))) (map (fn [x] (from-db-object x true)) dbc)))
@ -82,8 +87,20 @@
(with-open [dbc (find db collection 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
"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.collection/find-one ;; monger.multi.collection/find-one
;; ;;
(defn ^DBObject find-one (defn ^DBObject find-one
@ -106,7 +123,22 @@
(from-db-object ^DBObject (find-one db collection ref fields) keywordize))) (from-db-object ^DBObject (find-one db collection ref fields) keywordize)))
;; ;;
;; monger.collection/find-by-id ;; monger.multi.collection/find-and-modify
;;
(defn ^DBObject 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 (defn ^DBObject find-by-id
@ -125,10 +157,13 @@
(from-db-object ^DBObject (find-one-as-map db collection {:_id id}) true)) (from-db-object ^DBObject (find-one-as-map db collection {:_id id}) true))
([^DB db ^String collection id fields] ([^DB db ^String collection 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 db collection {:_id id} fields) true))) (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.collection/count ;; monger.multi.collection/count
;; ;;
(defn count (defn count
@ -137,3 +172,190 @@
(.count (.getCollection db (name collection)) (to-db-object {}))) (.count (.getCollection db (name collection)) (to-db-object {})))
(^long [^DB db ^String collection ^Map conditions] (^long [^DB db ^String collection ^Map conditions]
(.count (.getCollection db (name collection)) (to-db-object 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

@ -0,0 +1,407 @@
(set! *warn-on-reflection* true)
(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 mgcol]
[monger.result :as mgres]
[monger.test.helper :as helper])
(:use [clojure.test]
[monger.operators]
[monger.test.fixtures]))
(helper/connect!)
(defn drop-altdb
[f]
(mg/drop-db "altdb")
(f))
(use-fixtures :each drop-altdb)
;;
;; $inc
;;
(deftest increment-a-single-existing-field-using-$inc-modifier
(let [db (mg/get-db "altdb")
coll "scores"
oid (ObjectId.)]
(mgcol/insert db coll { :_id oid :username "l33r0y" :score 100 })
(mgcol/update db coll { :_id oid } { $inc { :score 20 } })
(is (= 120 (:score (mgcol/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.)]
(mgcol/insert db coll { :_id oid :username "l33r0y" })
(mgcol/update db coll { :_id oid } { $inc { :score 30 } })
(is (= 30 (:score (mgcol/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.)]
(mgcol/insert db coll { :_id oid :username "l33r0y" :score 100 :bonus 0 })
(mgcol/update db coll { :_id oid } {$inc { :score 20 :bonus 10 } })
(is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mgcol/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.)]
(mgcol/insert db coll { :_id oid :username "l33r0y" :score 100 })
(mgcol/update db coll { :_id oid } { $inc { :score 20 :bonus 10 } })
(is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mgcol/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.)]
(mgcol/insert db coll { :_id oid :weight 10.0 })
(mgcol/update db coll { :_id oid } { $set { :weight 20.5 } })
(is (= 20.5 (:weight (mgcol/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.)]
(mgcol/insert db coll { :_id oid :weight 10.0 })
(mgcol/update db coll { :_id oid } { $set { :height 17.2 } })
(is (= 17.2 (:height (mgcol/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.)]
(mgcol/insert db coll { :_id oid :weight 10.0 :height 15.2 })
(mgcol/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 db coll oid [:weight :height])))))
(deftest update-and-set-multiple-fields-using-$set-modifier
(let [db (mg/get-db "altdb")
coll "things"
oid (ObjectId.)]
(mgcol/insert db coll { :_id oid :weight 10.0 })
(mgcol/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 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.)]
(mgcol/insert db coll { :_id oid :title "Document 1" :published true })
(mgcol/update db coll { :_id oid } { $unset { :published 1 } })
(is (= { :_id oid :title "Document 1" } (mgcol/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.)]
(mgcol/insert db coll { :_id oid :title "Document 1" :published true :featured true })
(mgcol/update db coll { :_id oid } { $unset { :published 1 :featured true } })
(is (= { :_id oid :title "Document 1" } (mgcol/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.)]
(mgcol/insert db coll { :_id oid :title "Document 1" :published true })
(is (mgres/ok? (mgcol/update db coll { :_id oid } { $unset { :published 1 :featured true } })))
(is (= { :_id oid :title "Document 1" } (mgcol/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.)]
(mgcol/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 db coll oid)))))
(deftest setOnInsert-in-upsert-for-existing-document
(let [db (mg/get-db "altdb")
coll "docs"
before 123
now 456
oid (ObjectId.)]
(mgcol/insert db coll { :_id oid :firstseen before :lastseen before})
(mgcol/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 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"]
(mgcol/insert db coll { :_id oid :title title })
(mgcol/update db coll { :_id oid } { $push { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["modifiers"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update db coll { :_id oid } { $push { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update db coll { :_id oid } { $push { :tags ["modifiers" "operators"] } })
(is (= { :_id oid :title title :tags ["mongodb" ["modifiers" "operators"]] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update db coll { :_id oid } { $push { :tags "modifiers" } })
(mgcol/update db coll { :_id oid } { $push { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers" "modifiers"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title })
(mgcol/update db coll { :_id oid } { $pushAll { :tags ["mongodb" "docs"] } })
(is (= { :_id oid :title title :tags ["mongodb" "docs"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update db coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers" "docs"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["mongodb" "docs"] })
(mgcol/update db coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } })
(is (= { :_id oid :title title :tags ["mongodb" "docs" "modifiers" "docs"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title })
(mgcol/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["modifiers"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["mongodb"] })
(mgcol/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(mgcol/update db coll { :_id oid } { $addToSet { :tags "modifiers" } })
(is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["products" "apple" "reviews"] })
(mgcol/update db coll { :_id oid } { $pop { :tags 1 } })
(is (= { :_id oid :title title :tags ["products" "apple"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["products" "apple" "reviews"] })
(mgcol/update db coll { :_id oid } { $pop { :tags -1 } })
(is (= { :_id oid :title title :tags ["apple" "reviews"] } (mgcol/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"]
(mgcol/insert db coll { :_id oid :title title :tags ["products" "apple" "reviews"] :categories ["apple" "reviews" "drafts"] })
(mgcol/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 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"]
(mgcol/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 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 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"]
(mgcol/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 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 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"]
(mgcol/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 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 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]]
(mgcol/insert db coll { :_id oid :title title :measurements v })
(mgcol/update db coll { :_id oid } { $rename { :measurements "results" } })
(is (= { :_id oid :title title :results v } (mgcol/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}}]
(mgcol/insert db coll doc)
(let [res (mgcol/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"}]
(mgcol/insert db coll doc)
(let [res (mgcol/find-and-modify db coll conditions {} :remove true)]
(is (= (select-keys res [:name :level]) {:name "Sophie Bangs" :level 42}))
(is (empty? (mgcol/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 (mgcol/find-and-modify db coll doc doc :upsert true)]
(is (empty? res))
(is (select-keys (mgcol/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 (mgcol/find-and-modify db coll query doc :upsert true :return-new true)]
(is (:_id res))
(is (select-keys (mgcol/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)]
(mgcol/insert-batch db coll [doc1 doc2])
(let [res (mgcol/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

@ -0,0 +1,132 @@
(set! *warn-on-reflection* true)
(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])
(:use clojure.test
monger.operators
monger.test.fixtures))
(helper/connect!)
(defn drop-altdb
[f]
(mg/drop-db "altdb")
(f))
(use-fixtures :each drop-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

@ -0,0 +1,147 @@
(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 mgcol]
[monger.test.helper :as helper]
[monger.conversion :as mgcnv])
(:use clojure.test
monger.operators
monger.conversion
monger.test.fixtures))
(helper/connect!)
(defn drop-altdb
[f]
(mg/drop-db "altdb")
(f))
(use-fixtures :each drop-altdb)
;;
;; find
;;
(deftest find-full-document-when-collection-is-empty
(let [db (mg/get-db "altdb")
collection "docs"
cursor (mgcol/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? (mgcol/find-seq db collection)))))
(deftest find-multiple-documents-when-collection-is-empty
(let [db (mg/get-db "altdb")
collection "libraries"]
(is (empty? (mgcol/find db collection { :language "Scala" })))))
(deftest find-multiple-maps-when-collection-is-empty
(let [db (mg/get-db "altdb")
collection "libraries"]
(is (empty? (mgcol/find-maps db collection { :language "Scala" })))))
(deftest find-multiple-documents-by-regex
(let [db (mg/get-db "altdb")
collection "libraries"]
(mgcol/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Java", :name "nhibernate" }
{ :language "JavaScript", :name "sprout-core" }])
(is (= 2 (monger.core/count (mgcol/find db collection { :language #"Java*" }))))))
(deftest find-multiple-documents
(let [db (mg/get-db "altdb")
collection "libraries"]
(mgcol/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 (mgcol/find db collection { :language "Scala" }))))
(is (= 3 (.count (mgcol/find db collection { :language "Clojure" }))))
(is (empty? (mgcol/find db collection { :language "Java" })))))
(deftest find-document-specify-fields
(let [db (mg/get-db "altdb")
collection "libraries"
_ (mgcol/insert db collection { :language "Clojure", :name "monger" })
result (mgcol/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"]
(mgcol/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))
(mgcol/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"]
(mgcol/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }])
(doseq [doc (take 3 (mgcol/find-maps db collection { :language "Clojure" }))]
(is (= "Clojure" (:language doc))))))
(deftest find-multiple-maps
(let [db (mg/get-db "altdb")
collection "libraries"]
(mgcol/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }])
(is (= 1 (count (mgcol/find-maps db collection { :language "Scala" }))))
(is (= 3 (count (mgcol/find-maps db collection { :language "Clojure" }))))
(is (empty? (mgcol/find-maps db collection { :language "Java" })))
(is (empty? (mgcol/find-maps db collection { :language "Java" } [:language :name])))))
(deftest find-multiple-partial-documents
(let [db (mg/get-db "altdb")
collection "libraries"]
(mgcol/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }
{ :language "Clojure", :name "incanter" }
{ :language "Scala", :name "akka" }])
(let [scala-libs (mgcol/find db collection { :language "Scala" } [:name])
clojure-libs (mgcol/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? (mgcol/find db collection { :language "Erlang" } [:name]))))))
(deftest finds-one-as-map
(let [db (mg/get-db "altdb")
collection "libraries"]
(mgcol/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }])
(let [res (mgcol/find-one-as-map db collection { :name "langohr" })]
(is (map? res))
(is (= "langohr" (:name res)))
(is (= "Clojure" (:language res))))
(is (= 2 (count (mgcol/find-one-as-map db collection { :name "langohr" } [:name]))))
(is (= "langohr" (get (mgcol/find-one-as-map db collection { :name "langohr" } [:name] false) "name")))))
(deftest find-and-modify
(let [db (mg/get-db "altdb")
collection "libraries"]
(mgcol/insert-batch db collection [{ :language "Clojure", :name "monger" }
{ :language "Clojure", :name "langohr" }])))

View file

@ -0,0 +1,57 @@
(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)
(:use clojure.test
monger.test.fixtures
[clj-time.core :only [now secs ago from-now]]))
(helper/connect!)
(defn drop-altdb
[f]
(mg/drop-db "altdb")
(f))
(use-fixtures :each drop-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

@ -86,3 +86,104 @@
result (mc/insert db "widgets" doc)] result (mc/insert db "widgets" doc)]
(is (= (sort ["kw1" "kw2"]) (is (= (sort ["kw1" "kw2"])
(sort (get-in (mc/find-map-by-id db collection id) [:keyword1 :keyword2])))))) (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

@ -0,0 +1,183 @@
(set! *warn-on-reflection* true)
(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])
(:use clojure.test
monger.operators
monger.test.fixtures
[monger.conversion :only [to-db-object]]))
(helper/connect!)
(defn drop-altdb
[f]
(mg/drop-db "altdb")
(f))
(use-fixtures :each drop-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)))