From 3aa842fb0445b0a6813cc3f201a08b88f09429b2 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 12 Feb 2012 09:52:55 +0400 Subject: [PATCH 01/10] Remove commented out code --- src/monger/collection.clj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/monger/collection.clj b/src/monger/collection.clj index 7a6c76e..ec542cb 100644 --- a/src/monger/collection.clj +++ b/src/monger/collection.clj @@ -161,12 +161,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 From f8bb19b6ba7a2ec0632b037c29c24b8b51e30bee Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 12 Feb 2012 09:57:53 +0400 Subject: [PATCH 02/10] Add ChangeLog file, closes #8 --- ChangeLog.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 ChangeLog.md diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 0000000..a2c3b26 --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,23 @@ +## 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) +``` From c04df6e58cc9fc789d0a802237cb48a067213d6c Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 12 Feb 2012 10:00:46 +0400 Subject: [PATCH 03/10] No need to escape underscores here [ci skip] --- ChangeLog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index a2c3b26..b99afc4 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -12,12 +12,12 @@ instead of `keywordize` to better fit a more commonly needed case. ``` clojure ;; 3-arity in 1.0.0-beta2 -(monger.collection/find-one-as-map "documents" { :first_name "John" } [:first\_name, :last\_name, :age]) +(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) +(monger.collection/find-one-as-map "documents" { :first_name "John" } [:first_name, :last_name, :age] false) ``` From fe421cc0dbc98b123a6a4074c4cd6339a0987624 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 12 Feb 2012 10:13:39 +0400 Subject: [PATCH 04/10] Make it possible to opt-out of field keywordization in the query DSL An example: ``` clojure (with-collection coll (find {}) (limit 3) (sort { :population -1 }) (keywordize-fields false)) ``` --- src/monger/query.clj | 25 +++++++++++++++---------- test/monger/test/querying.clj | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/monger/query.clj b/src/monger/query.clj index 2b0092a..a4dc99a 100644 --- a/src/monger/query.clj +++ b/src/monger/query.clj @@ -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) })) diff --git a/test/monger/test/querying.clj b/test/monger/test/querying.clj index ca106d6..7abfc43 100644 --- a/test/monger/test/querying.clj +++ b/test/monger/test/querying.clj @@ -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]))))) From 1961aa71571fe21d01e32aa1aba51442d28be1e2 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 12 Feb 2012 10:15:45 +0400 Subject: [PATCH 05/10] ChangeLog update [ci skip] --- ChangeLog.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index b99afc4..5a1248a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -21,3 +21,18 @@ 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. From 7a68d83d6cb820ac25102f28664de7fd1a506341 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 12 Feb 2012 10:47:17 +0400 Subject: [PATCH 06/10] clj-time 0.3.6 --- project.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.clj b/project.clj index b602c72..e7cf32c 100644 --- a/project.clj +++ b/project.clj @@ -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 From 94f21e759758576daf487d8790f6f677bf8b5b72 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 12 Feb 2012 20:38:03 +0400 Subject: [PATCH 07/10] A better query example for the README [ci skip] --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 82df8b0..7d30114 100644 --- a/README.md +++ b/README.md @@ -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)) ``` From 7553925250e5149079fd43be3ee8671865ebe9b3 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Sun, 12 Feb 2012 20:39:23 +0400 Subject: [PATCH 08/10] Correct docstring [ci skip] --- src/monger/collection.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/monger/collection.clj b/src/monger/collection.clj index ec542cb..ddce83a 100644 --- a/src/monger/collection.clj +++ b/src/monger/collection.clj @@ -171,11 +171,11 @@ 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] (find-one collection { :_id id })) From f6a80fa40a7e07f1d61a52637a6af365c230b614 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Mon, 13 Feb 2012 22:52:03 +0400 Subject: [PATCH 09/10] Make sure monger.collection/find-by-id and /find-map-by-id fail fast when id is nil --- src/monger/collection.clj | 31 ++++++++++++++++++---------- test/monger/test/regular_finders.clj | 11 ++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/monger/collection.clj b/src/monger/collection.clj index ddce83a..b12b308 100644 --- a/src/monger/collection.clj +++ b/src/monger/collection.clj @@ -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. @@ -178,19 +191,25 @@ (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))) @@ -503,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))) diff --git a/test/monger/test/regular_finders.clj b/test/monger/test/regular_finders.clj index bad3f0a..fa636dd 100644 --- a/test/monger/test/regular_finders.clj +++ b/test/monger/test/regular_finders.clj @@ -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" From a4d5a0875ac44b515b4ed8637ee37cad1f01ea49 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Mon, 13 Feb 2012 22:52:53 +0400 Subject: [PATCH 10/10] Changelog update --- ChangeLog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 5a1248a..eee1785 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -36,3 +36,9 @@ It is now possible to opt-out of field keywordization in the query DSL: ``` 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