From bb169d3ae361cffac8ddfb08d9f9233b553bc3b2 Mon Sep 17 00:00:00 2001 From: Oleksandr Petrov Date: Tue, 8 Nov 2011 00:12:10 +0100 Subject: [PATCH 1/2] Adding operators DSL in order to use Clojure functions instead of hashes. Casbah has a similar concept called Bareword Operators. Korma uses operators a bit differently, but idea is quite same, too. One of the obvious advantages is that you can make sure you didn't screw make a typo in operator name during compile-time. Plus, we can guarantee that there is a subset of used / supported operators, and add them gradually, keeping track of them in one place, which will simplify tests, too. --- src/monger/operators.clj | 28 ++++++++++++++++++++++++++ test/monger/test/atomic_modifiers.clj | 29 +++++++++++++++------------ 2 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 src/monger/operators.clj diff --git a/src/monger/operators.clj b/src/monger/operators.clj new file mode 100644 index 0000000..d6e0017 --- /dev/null +++ b/src/monger/operators.clj @@ -0,0 +1,28 @@ +(ns monger.operators) + +(defmacro defoperator + [operator] + (let [operator-name (symbol (str operator))] + `(defn ~operator-name + [arg#] + { (str '~operator-name) arg# } + ))) +(defoperator $gt) +(defoperator $inc) +(defoperator $set) +(defoperator $unset) + +;; $lt +;; $lte +;; $all +;; $in +;; $set +;; $unset +;; $inc +;; $push +;; $pushAll +;; $addToSet +;; $pop +;; $pull +;; $pullAll +;; $rename \ No newline at end of file diff --git a/test/monger/test/atomic_modifiers.clj b/test/monger/test/atomic_modifiers.clj index f4a3e7a..02128fd 100644 --- a/test/monger/test/atomic_modifiers.clj +++ b/test/monger/test/atomic_modifiers.clj @@ -3,14 +3,16 @@ (ns monger.test.atomic-modifiers (:import [com.mongodb WriteResult WriteConcern DBCursor DBObject CommandResult$CommandFailure] [org.bson.types ObjectId] - [java.util Date]) + [java.util Date] + + ) (:require [monger core util] [monger.collection :as mgcol] [monger.result :as mgres]) (:use [clojure.test] + [monger.operators] [monger.test.fixtures])) - (defn purge-scores-collection [f] (purge-collection "scores" f)) @@ -28,8 +30,9 @@ (deftest increment-a-single-existing-field-using-$inc-modifier (let [coll "scores" oid (ObjectId.)] + (println ($inc { :score 20 } )) (mgcol/insert coll { :_id oid :username "l33r0y" :score 100 }) - (mgcol/update coll { :_id oid } { "$inc" { :score 20 } }) + (mgcol/update coll { :_id oid } ($inc { :score 20 } )) (is (= 120 (:score (mgcol/find-map-by-id coll oid)))))) @@ -37,7 +40,7 @@ (let [coll "scores" oid (ObjectId.)] (mgcol/insert coll { :_id oid :username "l33r0y" }) - (mgcol/update coll { :_id oid } { "$inc" { :score 30 } }) + (mgcol/update coll { :_id oid } ($inc { :score 30 } )) (is (= 30 (:score (mgcol/find-map-by-id coll oid)))))) @@ -45,7 +48,7 @@ (let [coll "scores" oid (ObjectId.)] (mgcol/insert coll { :_id oid :username "l33r0y" :score 100 :bonus 0 }) - (mgcol/update coll { :_id oid } { "$inc" { :score 20 :bonus 10 } }) + (mgcol/update coll { :_id oid } ($inc { :score 20 :bonus 10 } )) (is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mgcol/find-map-by-id coll oid))))) @@ -53,7 +56,7 @@ (let [coll "scores" oid (ObjectId.)] (mgcol/insert coll { :_id oid :username "l33r0y" :score 100 }) - (mgcol/update coll { :_id oid } { "$inc" { :score 20 :bonus 10 } }) + (mgcol/update coll { :_id oid } ($inc { :score 20 :bonus 10 } )) (is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mgcol/find-map-by-id coll oid))))) @@ -66,21 +69,21 @@ (let [coll "things" oid (ObjectId.)] (mgcol/insert coll { :_id oid :weight 10.0 }) - (mgcol/update coll { :_id oid } { "$set" { :weight 20.5 } }) + (mgcol/update coll { :_id oid } ( $set { :weight 20.5 } )) (is (= 20.5 (:weight (mgcol/find-map-by-id coll oid [:weight])))))) (deftest set-a-single-non-existing-field-using-$set-modifier (let [coll "things" oid (ObjectId.)] (mgcol/insert coll { :_id oid :weight 10.0 }) - (mgcol/update coll { :_id oid } { "$set" { :height 17.2 } }) + (mgcol/update coll { :_id oid } ( $set { :height 17.2 } )) (is (= 17.2 (:height (mgcol/find-map-by-id coll oid [:height])))))) (deftest update-multiple-existing-fields-using-$set-modifier (let [coll "things" oid (ObjectId.)] (mgcol/insert coll { :_id oid :weight 10.0 :height 15.2 }) - (mgcol/update coll { :_id oid } { "$set" { :weight 20.5 :height 25.6 } }) + (mgcol/update 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]))))) @@ -88,7 +91,7 @@ (let [coll "things" oid (ObjectId.)] (mgcol/insert coll { :_id oid :weight 10.0 }) - (mgcol/update coll { :_id oid } { "$set" { :weight 20.5 :height 25.6 } }) + (mgcol/update 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]))))) @@ -100,7 +103,7 @@ (let [coll "docs" oid (ObjectId.)] (mgcol/insert coll { :_id oid :title "Document 1" :published true }) - (mgcol/update coll { :_id oid } { "$unset" { :published 1 } }) + (mgcol/update coll { :_id oid } ( $unset { :published 1 } )) (is (= { :_id oid :title "Document 1" } (mgcol/find-map-by-id coll oid))))) @@ -108,7 +111,7 @@ (let [coll "docs" oid (ObjectId.)] (mgcol/insert coll { :_id oid :title "Document 1" :published true :featured true }) - (mgcol/update coll { :_id oid } { "$unset" { :published 1 :featured true } }) + (mgcol/update coll { :_id oid } ( $unset { :published 1 :featured true } )) (is (= { :_id oid :title "Document 1" } (mgcol/find-map-by-id coll oid))))) @@ -116,7 +119,7 @@ (let [coll "docs" oid (ObjectId.)] (mgcol/insert coll { :_id oid :title "Document 1" :published true }) - (is (mgres/ok? (mgcol/update coll { :_id oid } { "$unset" { :published 1 :featured true } }))) + (is (mgres/ok? (mgcol/update coll { :_id oid } ( $unset { :published 1 :featured true } )))) (is (= { :_id oid :title "Document 1" } (mgcol/find-map-by-id coll oid))))) From c1097021175ff4e34c7c7c2cf57cdf74ef43e1d8 Mon Sep 17 00:00:00 2001 From: "Michael S. Klishin" Date: Wed, 9 Nov 2011 12:40:22 +0400 Subject: [PATCH 2/2] Rewort $operator macros to evaluate to strings and not functions Unlike Casbah and Korma, we already use query language data structures as close to what MongoDB uses as possible (Clojure maps, vectors, numerics and strings are effectively JSON) so we don't need any layers on top, they won't improve anything. Having these operators is nice beacuse if you use atomic operators a lot, this will make sure Clojure compiler catches typos for you. It is completely opt-in, however. Finally, having a function inserted carries certain runtime performance cost and having $operator macros that evaluate to themselves does not. Per discussion with Alex. --- src/monger/operators.clj | 37 ++++++++--------- test/monger/test/atomic_modifiers.clj | 59 +++++++++++++-------------- 2 files changed, 47 insertions(+), 49 deletions(-) diff --git a/src/monger/operators.clj b/src/monger/operators.clj index d6e0017..ad94a82 100644 --- a/src/monger/operators.clj +++ b/src/monger/operators.clj @@ -2,27 +2,26 @@ (defmacro defoperator [operator] - (let [operator-name (symbol (str operator))] - `(defn ~operator-name - [arg#] - { (str '~operator-name) arg# } - ))) + (let [op# (str operator) + op-sym# (symbol op#)] + `(def ~op-sym# (str ~op#)))) + (defoperator $gt) (defoperator $inc) (defoperator $set) (defoperator $unset) -;; $lt -;; $lte -;; $all -;; $in -;; $set -;; $unset -;; $inc -;; $push -;; $pushAll -;; $addToSet -;; $pop -;; $pull -;; $pullAll -;; $rename \ No newline at end of file +(defoperator $lt) +(defoperator $lte) +(defoperator $all) +(defoperator $in) +(defoperator $set) +(defoperator $unset) +(defoperator $inc) +(defoperator $push) +(defoperator $pushAll) +(defoperator $addToSet) +(defoperator $pop) +(defoperator $pull) +(defoperator $pullAll) +(defoperator $rename) diff --git a/test/monger/test/atomic_modifiers.clj b/test/monger/test/atomic_modifiers.clj index 02128fd..95e5ebb 100644 --- a/test/monger/test/atomic_modifiers.clj +++ b/test/monger/test/atomic_modifiers.clj @@ -30,9 +30,8 @@ (deftest increment-a-single-existing-field-using-$inc-modifier (let [coll "scores" oid (ObjectId.)] - (println ($inc { :score 20 } )) (mgcol/insert coll { :_id oid :username "l33r0y" :score 100 }) - (mgcol/update coll { :_id oid } ($inc { :score 20 } )) + (mgcol/update coll { :_id oid } { $inc { :score 20 } }) (is (= 120 (:score (mgcol/find-map-by-id coll oid)))))) @@ -40,7 +39,7 @@ (let [coll "scores" oid (ObjectId.)] (mgcol/insert coll { :_id oid :username "l33r0y" }) - (mgcol/update coll { :_id oid } ($inc { :score 30 } )) + (mgcol/update coll { :_id oid } { $inc { :score 30 } }) (is (= 30 (:score (mgcol/find-map-by-id coll oid)))))) @@ -48,7 +47,7 @@ (let [coll "scores" oid (ObjectId.)] (mgcol/insert coll { :_id oid :username "l33r0y" :score 100 :bonus 0 }) - (mgcol/update coll { :_id oid } ($inc { :score 20 :bonus 10 } )) + (mgcol/update coll { :_id oid } {$inc { :score 20 :bonus 10 } }) (is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mgcol/find-map-by-id coll oid))))) @@ -56,7 +55,7 @@ (let [coll "scores" oid (ObjectId.)] (mgcol/insert coll { :_id oid :username "l33r0y" :score 100 }) - (mgcol/update coll { :_id oid } ($inc { :score 20 :bonus 10 } )) + (mgcol/update coll { :_id oid } { $inc { :score 20 :bonus 10 } }) (is (= { :_id oid :score 120 :bonus 10 :username "l33r0y" } (mgcol/find-map-by-id coll oid))))) @@ -69,21 +68,21 @@ (let [coll "things" oid (ObjectId.)] (mgcol/insert coll { :_id oid :weight 10.0 }) - (mgcol/update coll { :_id oid } ( $set { :weight 20.5 } )) + (mgcol/update coll { :_id oid } { $set { :weight 20.5 } }) (is (= 20.5 (:weight (mgcol/find-map-by-id coll oid [:weight])))))) (deftest set-a-single-non-existing-field-using-$set-modifier (let [coll "things" oid (ObjectId.)] (mgcol/insert coll { :_id oid :weight 10.0 }) - (mgcol/update coll { :_id oid } ( $set { :height 17.2 } )) + (mgcol/update coll { :_id oid } { $set { :height 17.2 } }) (is (= 17.2 (:height (mgcol/find-map-by-id coll oid [:height])))))) (deftest update-multiple-existing-fields-using-$set-modifier (let [coll "things" oid (ObjectId.)] (mgcol/insert coll { :_id oid :weight 10.0 :height 15.2 }) - (mgcol/update coll { :_id oid } ( $set { :weight 20.5 :height 25.6 } )) + (mgcol/update 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]))))) @@ -91,7 +90,7 @@ (let [coll "things" oid (ObjectId.)] (mgcol/insert coll { :_id oid :weight 10.0 }) - (mgcol/update coll { :_id oid } ($set { :weight 20.5 :height 25.6 } )) + (mgcol/update 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]))))) @@ -103,7 +102,7 @@ (let [coll "docs" oid (ObjectId.)] (mgcol/insert coll { :_id oid :title "Document 1" :published true }) - (mgcol/update coll { :_id oid } ( $unset { :published 1 } )) + (mgcol/update coll { :_id oid } { $unset { :published 1 } }) (is (= { :_id oid :title "Document 1" } (mgcol/find-map-by-id coll oid))))) @@ -111,7 +110,7 @@ (let [coll "docs" oid (ObjectId.)] (mgcol/insert coll { :_id oid :title "Document 1" :published true :featured true }) - (mgcol/update coll { :_id oid } ( $unset { :published 1 :featured true } )) + (mgcol/update coll { :_id oid } { $unset { :published 1 :featured true } }) (is (= { :_id oid :title "Document 1" } (mgcol/find-map-by-id coll oid))))) @@ -119,7 +118,7 @@ (let [coll "docs" oid (ObjectId.)] (mgcol/insert coll { :_id oid :title "Document 1" :published true }) - (is (mgres/ok? (mgcol/update coll { :_id oid } ( $unset { :published 1 :featured true } )))) + (is (mgres/ok? (mgcol/update coll { :_id oid } { $unset { :published 1 :featured true } }))) (is (= { :_id oid :title "Document 1" } (mgcol/find-map-by-id coll oid))))) @@ -132,7 +131,7 @@ oid (ObjectId.) title "$push modifier appends value to field"] (mgcol/insert coll { :_id oid :title title }) - (mgcol/update coll { :_id oid } { "$push" { :tags "modifiers" } }) + (mgcol/update coll { :_id oid } { $push { :tags "modifiers" } }) (is (= { :_id oid :title title :tags ["modifiers"] } (mgcol/find-map-by-id coll oid))))) (deftest add-value-to-an-existing-array-using-$push-modifier @@ -140,7 +139,7 @@ oid (ObjectId.) title "$push modifier appends value to field"] (mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) - (mgcol/update coll { :_id oid } { "$push" { :tags "modifiers" } }) + (mgcol/update coll { :_id oid } { $push { :tags "modifiers" } }) (is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mgcol/find-map-by-id coll oid))))) @@ -151,7 +150,7 @@ oid (ObjectId.) title "$push modifier appends value to field"] (mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) - (mgcol/update coll { :_id oid } { "$push" { :tags ["modifiers"] } }) + (mgcol/update coll { :_id oid } { $push { :tags ["modifiers"] } }) (is (= { :_id oid :title title :tags ["mongodb" ["modifiers"]] } (mgcol/find-map-by-id coll oid))))) @@ -161,8 +160,8 @@ oid (ObjectId.) title "$push modifier appends value to field"] (mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) - (mgcol/update coll { :_id oid } { "$push" { :tags "modifiers" } }) - (mgcol/update coll { :_id oid } { "$push" { :tags "modifiers" } }) + (mgcol/update coll { :_id oid } { $push { :tags "modifiers" } }) + (mgcol/update coll { :_id oid } { $push { :tags "modifiers" } }) (is (= { :_id oid :title title :tags ["mongodb" "modifiers" "modifiers"] } (mgcol/find-map-by-id coll oid))))) @@ -175,7 +174,7 @@ oid (ObjectId.) title "$pushAll modifier appends multiple values to field"] (mgcol/insert coll { :_id oid :title title }) - (mgcol/update coll { :_id oid } { "$pushAll" { :tags ["mongodb" "docs"] } }) + (mgcol/update coll { :_id oid } { $pushAll { :tags ["mongodb" "docs"] } }) (is (= { :_id oid :title title :tags ["mongodb" "docs"] } (mgcol/find-map-by-id coll oid))))) (deftest add-value-to-an-existing-array-using-$pushAll-modifier @@ -183,7 +182,7 @@ oid (ObjectId.) title "$pushAll modifier appends multiple values to field"] (mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) - (mgcol/update coll { :_id oid } { "$pushAll" { :tags ["modifiers" "docs"] } }) + (mgcol/update coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } }) (is (= { :_id oid :title title :tags ["mongodb" "modifiers" "docs"] } (mgcol/find-map-by-id coll oid))))) @@ -192,7 +191,7 @@ oid (ObjectId.) title "$pushAll modifier appends multiple values to field"] (mgcol/insert coll { :_id oid :title title :tags ["mongodb" "docs"] }) - (mgcol/update coll { :_id oid } { "$pushAll" { :tags ["modifiers" "docs"] } }) + (mgcol/update coll { :_id oid } { $pushAll { :tags ["modifiers" "docs"] } }) (is (= { :_id oid :title title :tags ["mongodb" "docs" "modifiers" "docs"] } (mgcol/find-map-by-id coll oid))))) @@ -205,7 +204,7 @@ oid (ObjectId.) title "$addToSet modifier appends value to field unless it is already there"] (mgcol/insert coll { :_id oid :title title }) - (mgcol/update coll { :_id oid } { "$addToSet" { :tags "modifiers" } }) + (mgcol/update coll { :_id oid } { $addToSet { :tags "modifiers" } }) (is (= { :_id oid :title title :tags ["modifiers"] } (mgcol/find-map-by-id coll oid))))) (deftest add-value-to-an-existing-array-using-$addToSet-modifier @@ -213,7 +212,7 @@ oid (ObjectId.) title "$addToSet modifier appends value to field unless it is already there"] (mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) - (mgcol/update coll { :_id oid } { "$addToSet" { :tags "modifiers" } }) + (mgcol/update coll { :_id oid } { $addToSet { :tags "modifiers" } }) (is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mgcol/find-map-by-id coll oid))))) @@ -222,8 +221,8 @@ oid (ObjectId.) title "$addToSet modifier appends value to field unless it is already there"] (mgcol/insert coll { :_id oid :title title :tags ["mongodb"] }) - (mgcol/update coll { :_id oid } { "$addToSet" { :tags "modifiers" } }) - (mgcol/update coll { :_id oid } { "$addToSet" { :tags "modifiers" } }) + (mgcol/update coll { :_id oid } { $addToSet { :tags "modifiers" } }) + (mgcol/update coll { :_id oid } { $addToSet { :tags "modifiers" } }) (is (= { :_id oid :title title :tags ["mongodb" "modifiers"] } (mgcol/find-map-by-id coll oid))))) @@ -236,7 +235,7 @@ oid (ObjectId.) title "$pop modifier removes last or first value in the array"] (mgcol/insert coll { :_id oid :title title :tags ["products" "apple" "reviews"] }) - (mgcol/update coll { :_id oid } { "$pop" { :tags 1 } }) + (mgcol/update coll { :_id oid } { $pop { :tags 1 } }) (is (= { :_id oid :title title :tags ["products" "apple"] } (mgcol/find-map-by-id coll oid))))) (deftest unshift-first-value-in-the-array-using-$pop-modifier @@ -244,7 +243,7 @@ oid (ObjectId.) title "$pop modifier removes last or first value in the array"] (mgcol/insert coll { :_id oid :title title :tags ["products" "apple" "reviews"] }) - (mgcol/update coll { :_id oid } { "$pop" { :tags -1 } }) + (mgcol/update coll { :_id oid } { $pop { :tags -1 } }) (is (= { :_id oid :title title :tags ["apple" "reviews"] } (mgcol/find-map-by-id coll oid))))) (deftest pop-last-values-from-multiple-arrays-using-$pop-modifier @@ -252,7 +251,7 @@ oid (ObjectId.) 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"] }) - (mgcol/update coll { :_id oid } { "$pop" { :tags 1 :categories 1 } }) + (mgcol/update 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))))) @@ -265,7 +264,7 @@ oid (ObjectId.) 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] }) - (mgcol/update coll { :_id oid } { "$pull" { :measurements 1.2 } }) + (mgcol/update 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))))) @@ -278,7 +277,7 @@ oid (ObjectId.) 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] }) - (mgcol/update coll { :_id oid } { "$pullAll" { :measurements [1.0 1.1 1.2] } }) + (mgcol/update 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))))) @@ -292,5 +291,5 @@ 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 coll { :_id oid :title title :measurements v }) - (mgcol/update coll { :_id oid } { "$rename" { :measurements "results" } }) + (mgcol/update coll { :_id oid } { $rename { :measurements "results" } }) (is (= { :_id oid :title title :results v } (mgcol/find-map-by-id coll oid)))))