better mapReduce apis
+ mapReduce is now the convience function that returns a cursor + runMapReduce can be called if you want the intermediate result meta-data + mapReduceResults will take the result meta-data and open a cursor on it
This commit is contained in:
parent
0a391e631b
commit
ece60d87ad
1 changed files with 76 additions and 5 deletions
|
@ -56,7 +56,10 @@ module Database.MongoDB
|
||||||
Direction(..),
|
Direction(..),
|
||||||
createIndex, dropIndex, dropIndexes, indexInformation,
|
createIndex, dropIndex, dropIndexes, indexInformation,
|
||||||
-- * Map-Reduce
|
-- * Map-Reduce
|
||||||
MapReduceOpt(..), mapReduce,
|
MapReduceOpt(..),
|
||||||
|
mapReduce, mapReduceWScopes,
|
||||||
|
runMapReduce, runMapReduceWScopes,
|
||||||
|
mapReduceResults,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
import Control.Exception
|
import Control.Exception
|
||||||
|
@ -653,18 +656,86 @@ mrOptToTuple (MROptFinalize f) = ("finalize", BsonJSCode f)
|
||||||
mrOptToTuple (MROptScope s) = ("scope", BsonDoc s)
|
mrOptToTuple (MROptScope s) = ("scope", BsonDoc s)
|
||||||
mrOptToTuple MROptVerbose = ("verbose", BsonBool True)
|
mrOptToTuple MROptVerbose = ("verbose", BsonBool True)
|
||||||
|
|
||||||
mapReduce :: Connection -> FullCollection
|
-- | Issue a map/reduce command and return the results metadata. If
|
||||||
|
-- all you care about is the actual map/reduce results you might want
|
||||||
|
-- to use the 'mapReduce' command instead.
|
||||||
|
--
|
||||||
|
-- The results meta-document will look something like this:
|
||||||
|
--
|
||||||
|
-- > {"result": "tmp.mr.mapreduce_1268095152_14",
|
||||||
|
-- > "timeMillis": 67,
|
||||||
|
-- > "counts": {"input": 4,
|
||||||
|
-- > "emit": 6,
|
||||||
|
-- > "output": 3},
|
||||||
|
-- > "ok": 1.0}
|
||||||
|
--
|
||||||
|
-- The /results/ field is the collection name within the same Database
|
||||||
|
-- that contain the results of the map/reduce.
|
||||||
|
runMapReduce :: Connection -> FullCollection
|
||||||
-> JSCode -- ^ mapping javascript function
|
-> JSCode -- ^ mapping javascript function
|
||||||
-> JSCode -- ^ reducing javascript function
|
-> JSCode -- ^ reducing javascript function
|
||||||
-> [MapReduceOpt]
|
-> [MapReduceOpt]
|
||||||
-> IO BsonDoc
|
-> IO BsonDoc
|
||||||
mapReduce c fc m r opts = do
|
runMapReduce c fc m r opts = do
|
||||||
let (db, col) = splitFullCol fc
|
let (db, col) = splitFullCol fc
|
||||||
doc = [("mapreduce", toBson col),
|
doc = [("mapreduce", toBson col),
|
||||||
("map", BsonCode m),
|
("map", BsonJSCode m),
|
||||||
("reduce", BsonCode r)] ++ List.map mrOptToTuple opts
|
("reduce", BsonJSCode r)] ++ List.map mrOptToTuple opts
|
||||||
runCommand c db $ toBsonDoc doc
|
runCommand c db $ toBsonDoc doc
|
||||||
|
|
||||||
|
-- | Issue a map/reduce command with associated scopes and return the
|
||||||
|
-- results metadata. If all you care about is the actual map/reduce
|
||||||
|
-- results you might want to use the 'mapReduce' command instead.
|
||||||
|
--
|
||||||
|
-- See 'runMapReduce' for more information about the form of the
|
||||||
|
-- result metadata.
|
||||||
|
runMapReduceWScopes :: Connection -> FullCollection
|
||||||
|
-> JSCode -- ^ mapping javascript function
|
||||||
|
-> BsonDoc -- ^ Scope for mapping function
|
||||||
|
-> JSCode -- ^ reducing javascript function
|
||||||
|
-> BsonDoc -- ^ Scope for reducing function
|
||||||
|
-> [MapReduceOpt]
|
||||||
|
-> IO BsonDoc
|
||||||
|
runMapReduceWScopes c fc m ms r rs opts = do
|
||||||
|
let (db, col) = splitFullCol fc
|
||||||
|
doc = [("mapreduce", toBson col),
|
||||||
|
("map", BsonJSCodeWScope m ms),
|
||||||
|
("reduce", BsonJSCodeWScope r rs)] ++ List.map mrOptToTuple opts
|
||||||
|
runCommand c db $ toBsonDoc doc
|
||||||
|
|
||||||
|
-- | Given a result metadata from a 'mapReduce' command (or
|
||||||
|
-- 'mapReduceWScope'), issue the 'find' command that will produce the
|
||||||
|
-- actual map/reduce results.
|
||||||
|
mapReduceResults :: Connection -> Database -> BsonDoc -> IO Cursor
|
||||||
|
mapReduceResults c db r = do
|
||||||
|
let col = case List.lookup (s2L "result") r of
|
||||||
|
Just bCol -> fromBson bCol
|
||||||
|
Nothing -> throwOpFailure "No 'result' in mapReduce response"
|
||||||
|
fc = L.append (L.append db $ s2L ".") col
|
||||||
|
find c fc []
|
||||||
|
|
||||||
|
-- | Run map/reduce and produce a cursor on the results.
|
||||||
|
mapReduce :: Connection -> FullCollection
|
||||||
|
-> JSCode -- ^ mapping javascript function
|
||||||
|
-> JSCode -- ^ reducing javascript function
|
||||||
|
-> [MapReduceOpt]
|
||||||
|
-> IO Cursor
|
||||||
|
mapReduce c fc m r opts =
|
||||||
|
runMapReduce c fc m r opts >>= mapReduceResults c (fst $ splitFullCol fc)
|
||||||
|
|
||||||
|
-- | Run map/reduce with associated scopes and produce a cursor on the
|
||||||
|
-- results.
|
||||||
|
mapReduceWScopes :: Connection -> FullCollection
|
||||||
|
-> JSCode -- ^ mapping javascript function
|
||||||
|
-> BsonDoc -- ^ Scope for mapping function
|
||||||
|
-> JSCode -- ^ reducing javascript function
|
||||||
|
-> BsonDoc -- ^ Scope for mapping function
|
||||||
|
-> [MapReduceOpt]
|
||||||
|
-> IO Cursor
|
||||||
|
mapReduceWScopes c fc m ms r rs opts =
|
||||||
|
runMapReduceWScopes c fc m ms r rs opts >>=
|
||||||
|
mapReduceResults c (fst $ splitFullCol fc)
|
||||||
|
|
||||||
-- | Conveniently stores the /BsonDoc/ to the /FullCollection/
|
-- | Conveniently stores the /BsonDoc/ to the /FullCollection/
|
||||||
-- if there is an _id present in the /BsonDoc/ then it already has
|
-- if there is an _id present in the /BsonDoc/ then it already has
|
||||||
-- a place in the DB, so we update it using the _id, otherwise
|
-- a place in the DB, so we update it using the _id, otherwise
|
||||||
|
|
Loading…
Reference in a new issue