Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Toby Hede 2012-02-14 21:49:56 +11:00
commit d5cce8c97b
7 changed files with 118 additions and 35 deletions

44
ChangeLog.md Normal file
View file

@ -0,0 +1,44 @@
## Changes between 1.0.0-beta1 and 1.0.0-beta2
### 3-arity of monger.collection/find-one-as-map now takes a vector of fields
3-arity of monger.collection/find-one-as-map now takes a vector of fields
instead of `keywordize` to better fit a more commonly needed case.
``` clojure
;; 3-arity in 1.0.0-beta1
(monger.collection/find-one-as-map "documents" { :first_name "John" } false)
```
``` clojure
;; 3-arity in 1.0.0-beta2
(monger.collection/find-one-as-map "documents" { :first_name "John" } [:first_name, :last_name, :age])
```
If you need to use `keywordize`, use 4-arity:
``` clojure
(monger.collection/find-one-as-map "documents" { :first_name "John" } [:first_name, :last_name, :age] false)
```
### Query DSL has a way to specify if fields need to be keywordized
It is now possible to opt-out of field keywordization in the query DSL:
``` clojure
(with-collection coll
(find {})
(limit 3)
(sort { :population -1 })
(keywordize-fields false))
```
the default value is still true, field names will be converted to keywords.
### monger.collection/find-by-id and /find-map-by-id fail fast when id is nil
monger.collection/find-by-id and /find-map-by-id now will throw IllegalArgumentException when id is nil

View file

@ -216,13 +216,13 @@ for client libraries like Monger.
Here is what monger.query DSL feels like:
``` clojure
(with-collection "docs"
(find { :inception_year { $lt 2000 $gte 2011 } })
(fields [ :inception_year :name ])
(with-collection "movies"
(find { :year { $lt 2010 $gte 2000 }, :revenue { $gt 20000000 } })
(fields [ :year :title :producer :cast :budget :revenue ])
(sort-by { :revenue -1 })
(skip 10)
(limit 20)
(batch-size 50)
(hint "my-index-name")
(hint "year-by-year-revenue-idx")
(snapshot))
```

View file

@ -15,7 +15,7 @@
[com.novemberain/validateur "1.0.0"]]
}
:dev-dependencies [[org.clojure/data.json "0.1.2" :exclusions [org.clojure/clojure]]
[clj-time "0.3.3" :exclusions [org.clojure/clojure]]
[clj-time "0.3.6" :exclusions [org.clojure/clojure]]
[codox "0.3.4" :exclusions [org.clojure/clojure]]]
:dev-resources-path "test/resources"
:warn-on-reflection true

View file

@ -15,6 +15,20 @@
(:require [monger core result])
(:use [monger.conversion]))
;;
;; Implementation
;;
(defn- fields-to-db-object
[^List fields]
(zipmap fields (repeat 1)))
(definline check-not-nil!
[ref message]
`(when (nil? ~ref)
(throw (IllegalArgumentException. ~message))))
;;
;; API
;;
@ -66,7 +80,6 @@
;;
;; monger.collection/find
;;
(declare fields-to-db-object)
(defn ^DBCursor find
"Queries for objects in this collection.
@ -161,12 +174,6 @@
(from-db-object ^DBObject (find-one collection ref fields) keywordize)))
; ([^String collection ^Map ref keywordize]
; (from-db-object ^DBObject (find-one collection ref fields) keywordize))
; ([^String collection ^Map ref ^List fields keywordize]
; (from-db-object ^DBObject (find-one collection ref fields) keywordize)))
;;
;; monger.collection/find-by-id
@ -177,26 +184,32 @@
EXAMPLES:
(mgcol/find-one-by-id collection \"4ef45ab4744e9fd632640e2d\")
(mgcol/find-one-by-id collection (ObjectId. \"4ef45ab4744e9fd632640e2d\"))
;; Return only :language field.
;; Note that _id field is always returned.
(mgcol/find-one-by-id collection \"4ef45ab4744e9fd632640e2d\" [:language])
(mgcol/find-one-by-id collection (ObjectId. \"4ef45ab4744e9fd632640e2d\") [:language])
"
([^String collection id]
(check-not-nil! id "id must not be nil")
(find-one collection { :_id id }))
([^String collection id ^List fields]
(check-not-nil! id "id must not be nil")
(find-one collection { :_id id } fields))
([^DB db ^String collection id ^List fields]
(check-not-nil! id "id must not be nil")
(find-one db collection { :_id id } fields)))
(defn ^IPersistentMap find-map-by-id
"Returns a single object, converted to map with matching _id field."
([^String collection id]
(check-not-nil! id "id must not be nil")
(from-db-object ^DBObject (find-one-as-map collection { :_id id }) true))
([^String collection id keywordize]
(check-not-nil! id "id must not be nil")
(from-db-object ^DBObject (find-one-as-map collection { :_id id }) keywordize))
([^String collection id ^List fields keywordize]
(check-not-nil! id "id must not be nil")
(from-db-object ^DBObject (find-one-as-map collection { :_id id } fields) keywordize)))
@ -509,13 +522,3 @@
([^DB db ^String collection ^String key ^Map query]
(let [^DBCollection coll (.getCollection db collection)]
(.distinct coll ^String (to-db-object key) ^DBObject (to-db-object query)))))
;;
;; Implementation
;;
(defn- fields-to-db-object
[^List fields]
(zipmap fields (repeat 1)))

View file

@ -36,14 +36,15 @@
(defn empty-query
([]
{
:query {}
:sort {}
:fields []
:skip 0
:limit 0
:batch-size 256
:hint nil
:snapshot false
:query {}
:sort {}
:fields []
:skip 0
:limit 0
:batch-size 256
:hint nil
:snapshot false
:keywordize-fields true
})
([^DBCollection coll]
(merge (empty-query) { :collection coll })))
@ -53,7 +54,7 @@
(to-db-object (zipmap fields (repeat 1))))
(defn exec
[{ :keys [collection query fields skip limit sort batch-size hint snapshot read-preference] :or { limit 0 batch-size 256 skip 0 } }]
[{ :keys [collection query fields skip limit sort batch-size hint snapshot read-preference keywordize-fields] :or { limit 0 batch-size 256 skip 0 } }]
(let [cursor (doto ^DBCursor (.find ^DBCollection collection (to-db-object query) (fields-to-db-object fields))
(.limit limit)
(.skip skip)
@ -64,7 +65,7 @@
(.snapshot cursor))
(when read-preference
(.setReadPreference cursor read-preference))
(map (fn [x] (from-db-object x true))
(map (fn [x] (from-db-object x keywordize-fields))
(seq cursor))))
;;
@ -107,6 +108,10 @@
[m ^ReadPreference rp]
(merge m { :read-preference rp }))
(defn keywordize-fields
[m bool]
(merge m { :keywordize-fields bool }))
(defn paginate
[m & { :keys [page per-page] :or { page 1 per-page 10 } }]
(merge m { :limit per-page :skip (monger.internal.pagination/offset-for page per-page) }))

View file

@ -260,3 +260,23 @@
(merge top3)
(merge by-population-desc))]
(is (= result [ca-doc tx-doc ny-doc]))))
(deftest combined-querying-dsl-example2
(let [coll "docs"
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" }
ny-doc { :_id (ObjectId.) :name "New York" :iso "NY" :population 19378102 :joined_in 1788 :capital "Albany" }
ca-doc { :_id (ObjectId.) :name "California" :iso "CA" :population 37253956 :joined_in 1850 :capital "Sacramento" }
tx-doc { :_id (ObjectId.) :name "Texas" :iso "TX" :population 25145561 :joined_in 1845 :capital "Austin" }
top3 (partial-query (limit 3))
by-population-desc (partial-query (sort { :population -1 }))
_ (mgcol/insert-batch coll [ma-doc de-doc ny-doc ca-doc tx-doc])
result (with-collection coll
(find {})
(merge top3)
(merge by-population-desc)
(keywordize-fields false))]
;; documents have fields as strings,
;; not keywords
(is (= (map #(% "name") result)
(map #(% :name) [ca-doc tx-doc ny-doc])))))

View file

@ -101,6 +101,11 @@
doc-id (monger.util/random-uuid)]
(is (nil? (mgcol/find-by-id collection doc-id)))))
(deftest find-full-document-by-string-id-when-id-is-nil
(let [collection "libraries"
doc-id nil]
(is (thrown? IllegalArgumentException (mgcol/find-by-id collection doc-id)))))
(deftest find-full-document-by-object-id-when-that-document-does-not-exist
(let [collection "libraries"
doc-id (ObjectId.)]
@ -111,6 +116,12 @@
doc-id (monger.util/random-uuid)]
(is (nil? (mgcol/find-map-by-id collection doc-id)))))
(deftest find-full-document-by-id-as-map-when-id-is-nil
(let [collection "libraries"
doc-id nil]
(is (thrown? IllegalArgumentException
(mgcol/find-map-by-id collection doc-id)))))
(deftest find-full-document-by-string-id-when-document-does-exist
(let [collection "libraries"