/casbah-core/src/main/scala/map_reduce/MapReduceCommand.scala

https://github.com/derzzle/casbah · Scala · 157 lines · 95 code · 21 blank · 41 comment · 0 complexity · 8b3a217a5db4a5d14ef922c27776f6af MD5 · raw file

  1. /**
  2. * Copyright (c) 2010 10gen, Inc. <http://10gen.com>
  3. * Copyright (c) 2009, 2010 Novus Partners, Inc. <http://novus.com>
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. * For questions and comments about this product, please see the project page at:
  18. *
  19. * http://github.com/mongodb/casbah
  20. *
  21. */
  22. package com.mongodb.casbah
  23. package map_reduce
  24. import com.mongodb.casbah.Imports._
  25. import com.mongodb.casbah.util.Logging
  26. import scalaj.collection.Imports._
  27. class MapReduceException(msg: String) extends MongoException("MongoDB Map/Reduce Error: " + msg)
  28. trait MapReduceOutputTarget
  29. case class MapReduceStandardOutput(collection: String) extends MapReduceOutputTarget
  30. case class MapReduceMergeOutput(collection: String) extends MapReduceOutputTarget
  31. case class MapReduceReduceOutput(collection: String) extends MapReduceOutputTarget
  32. case object MapReduceInlineOutput extends MapReduceOutputTarget
  33. /**
  34. * Wrapper Object to provide apply methods for the MapReduceCommand class.
  35. *
  36. * @see <a href="http://www.mongodb.org/display/DOCS/MapReduce">The MongoDB Map/Reduce Documentation</a>
  37. *
  38. * @author Brendan W. McAdams <brendan@10gen.com>
  39. */
  40. object MapReduceCommand {
  41. def apply(input: String, map: JSFunction,
  42. reduce: JSFunction,
  43. output: MapReduceOutputTarget,
  44. query: Option[DBObject] = None,
  45. sort: Option[DBObject] = None,
  46. limit: Option[Int] = None,
  47. finalizeFunction: Option[JSFunction] = None,
  48. jsScope: Option[String] = None,
  49. verbose: Boolean = false) = {
  50. val mrc = new MapReduceCommand()
  51. mrc.input = input
  52. mrc.map = map
  53. mrc.reduce = reduce
  54. mrc.output = output
  55. mrc.query = query
  56. mrc.sort = sort
  57. mrc.limit = limit
  58. mrc.finalizeFunction = finalizeFunction
  59. mrc.jsScope = jsScope
  60. mrc.verbose = verbose
  61. mrc
  62. }
  63. }
  64. /**
  65. * Wrapper class for invoking MongoDB mapReduces.
  66. *
  67. * The Java driver doesn't provide support for many of the possible options in the latest
  68. * versions of MongoDB, so this wrapper class is used in it's place, and passed directly to
  69. * a db.runCommand call.
  70. *
  71. * @todo Integrate support for Lift's JavaScript DSL
  72. *
  73. * @see http://www.mongodb.org/display/DOCS/MapReduce
  74. *
  75. * @author Brendan W. McAdams <brendan@10gen.com>
  76. */
  77. class MapReduceCommand protected[mongodb] () {
  78. var input: String = ""
  79. var map: JSFunction = ""
  80. var reduce: JSFunction = ""
  81. var verbose = false // if true, provides statistics on job execution
  82. var output: MapReduceOutputTarget = MapReduceInlineOutput
  83. var query: Option[DBObject] = None
  84. var sort: Option[DBObject] = None
  85. var limit: Option[Int] = None
  86. var finalizeFunction: Option[JSFunction] = None
  87. var jsScope: Option[String] = None
  88. def toDBObject = {
  89. val dataObj = MongoDBObject.newBuilder
  90. input match {
  91. case "" => throw new MapReduceException("input must be defined.")
  92. case null => throw new MapReduceException("input must be defined.")
  93. case other => dataObj += "mapreduce" -> input
  94. }
  95. map match {
  96. case "" => throw new MapReduceException("map must be defined.")
  97. case null => throw new MapReduceException("map must be defined.")
  98. case other => dataObj += "map" -> map.toString
  99. }
  100. reduce match {
  101. case "" => throw new MapReduceException("reduce must be defined.")
  102. case null => throw new MapReduceException("reduce must be defined.")
  103. case other => dataObj += "reduce" -> reduce.toString
  104. }
  105. dataObj += "verbose" -> verbose
  106. dataObj += "out" -> (output match {
  107. case MapReduceStandardOutput(coll: String) => coll
  108. case MapReduceMergeOutput(coll: String) => MongoDBObject("merge" -> coll)
  109. case MapReduceReduceOutput(coll: String) => MongoDBObject("reduce" -> coll)
  110. case MapReduceInlineOutput => MongoDBObject("inline" -> true)
  111. case other => throw new IllegalArgumentException("Invalid Output Type '%s'".format(other))
  112. })
  113. query match {
  114. case Some(q) => dataObj += "query" -> q
  115. case None => {}
  116. }
  117. sort match {
  118. case Some(s) => dataObj += "sort" -> s
  119. case None => {}
  120. }
  121. limit match {
  122. case Some(i) => dataObj += "limit" -> i
  123. case None => {}
  124. }
  125. finalizeFunction match {
  126. case Some(fF) => dataObj += "finalize" -> fF.toString
  127. case None => {}
  128. }
  129. jsScope match {
  130. case Some(s) => dataObj += "scope" -> s
  131. case None => {}
  132. }
  133. dataObj.result
  134. }
  135. override def toString = toDBObject.toString
  136. }