Merge branch 'map/reduce'
This commit is contained in:
commit
aee8862bc6
3 changed files with 91 additions and 13 deletions
|
|
@ -9,7 +9,9 @@
|
|||
|
||||
(ns monger.collection
|
||||
(:refer-clojure :exclude [find remove count drop])
|
||||
(:import (com.mongodb Mongo DB DBCollection WriteResult DBObject WriteConcern DBCursor) (java.util List Map) (clojure.lang IPersistentMap ISeq))
|
||||
(:import [com.mongodb Mongo DB DBCollection WriteResult DBObject WriteConcern DBCursor MapReduceCommand MapReduceCommand$OutputType]
|
||||
[java.util List Map]
|
||||
[clojure.lang IPersistentMap ISeq])
|
||||
(:require [monger core result])
|
||||
(:use [monger.conversion]))
|
||||
|
||||
|
|
@ -281,6 +283,20 @@
|
|||
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* from)]
|
||||
(.rename coll to drop-target))))
|
||||
|
||||
;;
|
||||
;; Map/Reduce
|
||||
;;
|
||||
|
||||
(defn map-reduce
|
||||
([^String collection, ^String js-mapper, ^String js-reducer, ^String output, ^Map query]
|
||||
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)]
|
||||
(.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]
|
||||
(let [^DBCollection coll (.getCollection monger.core/*mongodb-database* collection)]
|
||||
(.mapReduce coll js-mapper js-reducer output output-type (to-db-object query)))))
|
||||
|
||||
|
||||
|
||||
;;
|
||||
;; Implementation
|
||||
;;
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
;; You must not remove this notice, or any other, from this software.
|
||||
|
||||
(ns monger.result
|
||||
(:import (com.mongodb DBObject WriteResult)
|
||||
(clojure.lang IPersistentMap))
|
||||
(:import [com.mongodb DBObject WriteResult MapReduceOutput]
|
||||
[clojure.lang IPersistentMap])
|
||||
(:require [monger conversion]))
|
||||
|
||||
|
||||
|
|
@ -46,4 +46,9 @@
|
|||
(has-error? (.getLastError result)))
|
||||
(updated-existing?
|
||||
[^WriteResult result]
|
||||
(updated-existing? (.getLastError result))))
|
||||
(updated-existing? (.getLastError result)))
|
||||
|
||||
MapReduceOutput
|
||||
(ok?
|
||||
[^MapReduceOutput result]
|
||||
(ok? ^DBObject (.getRaw result))))
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
(set! *warn-on-reflection* true)
|
||||
|
||||
(ns monger.test.collection
|
||||
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject CommandResult$CommandFailure]
|
||||
(:import [com.mongodb WriteResult WriteConcern DBCursor DBObject CommandResult$CommandFailure MapReduceOutput MapReduceCommand MapReduceCommand$OutputType]
|
||||
[org.bson.types ObjectId]
|
||||
[java.util Date])
|
||||
(:require [monger core result util conversion]
|
||||
(:require [monger core util]
|
||||
[clojure stacktrace]
|
||||
[monger.collection :as mgcol])
|
||||
[monger.collection :as mgcol]
|
||||
[monger.result :as mgres]
|
||||
[monger.conversion :as mgcnv])
|
||||
(:use [clojure.test]))
|
||||
|
||||
(monger.core/connect!)
|
||||
|
|
@ -60,7 +62,7 @@
|
|||
|
||||
(deftest insert-a-basic-db-object-without-id-and-with-default-write-concern
|
||||
(let [collection "people"
|
||||
doc (monger.conversion/to-db-object { :name "Joe", :age 30 })]
|
||||
doc (mgcnv/to-db-object { :name "Joe", :age 30 })]
|
||||
(is (nil? (.get ^DBObject doc "_id")))
|
||||
(mgcol/insert "people" doc)
|
||||
(is (not (nil? (monger.util/get-id doc))))))
|
||||
|
|
@ -160,8 +162,8 @@
|
|||
(mgcol/insert collection doc)
|
||||
(def ^DBObject found-one (mgcol/find-one collection { :language "Clojure" }))
|
||||
(is (= (:_id doc) (monger.util/get-id found-one)))
|
||||
(is (= (monger.conversion/from-db-object found-one true) doc))
|
||||
(is (= (monger.conversion/to-db-object doc) found-one))))
|
||||
(is (= (mgcnv/from-db-object found-one true) doc))
|
||||
(is (= (mgcnv/to-db-object doc) found-one))))
|
||||
|
||||
|
||||
(deftest find-one-full-document-as-map-when-collection-has-matches
|
||||
|
|
@ -289,7 +291,7 @@
|
|||
{ :language "Clojure", :name "incanter" }
|
||||
{ :language "Scala", :name "akka" }])
|
||||
(doseq [doc (take 3 (map (fn [dbo]
|
||||
(monger.conversion/from-db-object dbo true))
|
||||
(mgcnv/from-db-object dbo true))
|
||||
(mgcol/find-seq collection { :language "Clojure" })))]
|
||||
(is (= "Clojure" (:language doc))))))
|
||||
|
||||
|
|
@ -326,7 +328,7 @@
|
|||
(is (= 1 (.count scala-libs)))
|
||||
(is (= 3 (.count clojure-libs)))
|
||||
(doseq [i clojure-libs]
|
||||
(let [doc (monger.conversion/from-db-object i true)]
|
||||
(let [doc (mgcnv/from-db-object i true)]
|
||||
(is (= (:language doc) "Clojure"))))
|
||||
(is (empty? (mgcol/find collection { :language "Erlang" } [:name]))))))
|
||||
|
||||
|
|
@ -408,7 +410,7 @@
|
|||
|
||||
(deftest save-a-new-basic-db-object
|
||||
(let [collection "people"
|
||||
doc (monger.conversion/to-db-object { :name "Joe", :age 30 })]
|
||||
doc (mgcnv/to-db-object { :name "Joe", :age 30 })]
|
||||
(is (nil? (monger.util/get-id doc)))
|
||||
(mgcol/save "people" doc)
|
||||
(is (not (nil? (monger.util/get-id doc))))))
|
||||
|
|
@ -495,3 +497,58 @@
|
|||
(is (not (mgcol/exists? collection)))
|
||||
(is (mgcol/exists? "gadgets"))
|
||||
(mgcol/drop "gadgets")))
|
||||
|
||||
|
||||
;;
|
||||
;; Map/Reduce
|
||||
;;
|
||||
|
||||
(let [collection "widgets"
|
||||
mapper "function() {
|
||||
emit(this.state, this.price * this.quantity)
|
||||
}"
|
||||
reducer "function(key, values) {
|
||||
var result = 0;
|
||||
values.forEach(function(v) { result += v });
|
||||
|
||||
return result;
|
||||
}"
|
||||
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 }]
|
||||
expected [{:_id "CA", :value 204.9} {:_id "IL", :value 39.5} {:_id "NY", :value 697.0}]]
|
||||
(deftest basic-inline-map-reduce-example
|
||||
(mgcol/remove collection)
|
||||
(is (mgres/ok? (mgcol/insert-batch collection batch)))
|
||||
(let [output (mgcol/map-reduce collection mapper reducer nil MapReduceCommand$OutputType/INLINE {})
|
||||
results (mgcnv/from-db-object ^DBObject (.results ^MapReduceOutput output) true)]
|
||||
(mgres/ok? output)
|
||||
(is (= expected results))))
|
||||
|
||||
(deftest basic-map-reduce-example-that-replaces-named-collection
|
||||
(mgcol/remove collection)
|
||||
(is (mgres/ok? (mgcol/insert-batch collection batch)))
|
||||
(let [output (mgcol/map-reduce collection mapper reducer "mr_outputs" {})
|
||||
results (mgcnv/from-db-object ^DBObject (.results ^MapReduceOutput output) true)]
|
||||
(mgres/ok? output)
|
||||
(is (= 3 (monger.core/count results)))
|
||||
(is (= expected
|
||||
(map #(mgcnv/from-db-object % true) (seq results))))
|
||||
(is (= expected
|
||||
(map #(mgcnv/from-db-object % true) (mgcol/find "mr_outputs"))))
|
||||
(.drop ^MapReduceOutput output)))
|
||||
|
||||
(deftest basic-map-reduce-example-that-merged-results-into-named-collection
|
||||
(mgcol/remove collection)
|
||||
(is (mgres/ok? (mgcol/insert-batch collection batch)))
|
||||
(mgcol/map-reduce collection mapper reducer "merged_mr_outputs" MapReduceCommand$OutputType/MERGE {})
|
||||
(is (mgres/ok? (mgcol/insert collection { :state "OR" :price 17.95 :quantity 4 })))
|
||||
(let [output (mgcol/map-reduce collection mapper reducer "merged_mr_outputs" MapReduceCommand$OutputType/MERGE {})]
|
||||
(mgres/ok? output)
|
||||
(is (= 4 (monger.core/count (.results ^MapReduceOutput output))))
|
||||
(is (= ["CA" "IL" "NY" "OR"]
|
||||
(map :_id (mgcol/find-maps "merged_mr_outputs"))))
|
||||
(.drop ^MapReduceOutput output))))
|
||||
|
|
|
|||
Loading…
Reference in a new issue