lib/mongoid/contextual/map_reduce.rb in mongoid-5.4.1 vs lib/mongoid/contextual/map_reduce.rb in mongoid-6.0.0.beta
- old
+ new
@@ -30,17 +30,16 @@
#
# @return [ Enumerator ] The enumerator.
#
# @since 3.0.0
def each
- validate_out!
if block_given?
- @map_reduce.each do |doc|
+ documents.each do |doc|
yield doc
end
else
- @map_reduce.to_enum
+ to_enum
end
end
# Get the number of documents emitted by the map/reduce.
#
@@ -63,11 +62,11 @@
#
# @return [ MapReduce ] The map reduce.
#
# @since 3.0.0
def finalize(function)
- @map_reduce = @map_reduce.finalize(function)
+ command[:finalize] = function
self
end
# Initialize the new map/reduce directive.
#
@@ -78,13 +77,14 @@
# @param [ String ] map The map js function.
# @param [ String ] reduce The reduce js function.
#
# @since 3.0.0
def initialize(collection, criteria, map, reduce)
- @collection = collection
- @criteria = criteria
- @map_reduce = @criteria.view.map_reduce(map, reduce)
+ @collection, @criteria = collection, criteria
+ command[:mapreduce] = collection.name.to_s
+ command[:map], command[:reduce] = map, reduce
+ apply_criteria_options
end
# Get the number of documents that were input into the map/reduce.
#
# @example Get the count of input documents.
@@ -104,16 +104,15 @@
#
# @return [ MapReduce ] The map/reduce.
#
# @since 3.0.0
def js_mode
- @map_reduce = @map_reduce.js_mode(true)
+ command[:jsMode] = true
self
end
# Specifies where the map/reduce output is to be stored.
- # Please see MongoDB documentation for supported map reduce options.
#
# @example Store output in memory.
# map_reduce.out(inline: 1)
#
# @example Store output in a collection, replacing existing documents.
@@ -123,24 +122,21 @@
# map_reduce.out(merge: "collection_name")
#
# @example Store output in a collection, reducing existing documents.
# map_reduce.out(reduce: "collection_name")
#
- # @example Return results from map reduce.
- # map_reduce.out(inline: 1)
- #
# @param [ Hash ] location The place to store the results.
#
# @return [ MapReduce ] The map/reduce object.
#
# @since 3.0.0
def out(location)
normalized = location.dup
normalized.update_values do |value|
value.is_a?(::Symbol) ? value.to_s : value
end
- @map_reduce = @map_reduce.out(normalized)
+ command[:out] = normalized
self
end
# Get the number of documents output by the map/reduce.
#
@@ -161,16 +157,12 @@
#
# @return [ Hash ] The raw output.
#
# @since 3.0.0
def raw
- validate_out!
- cmd = command
- opts = { read: cmd.delete(:read).options } if cmd[:read]
- @map_reduce.database.command(cmd, opts || {}).first
+ results
end
- alias :results :raw
# Execute the map/reduce, returning the raw output.
# Useful when you don't care about map/reduce's ouptut.
#
# @example Run the map reduce
@@ -202,11 +194,11 @@
#
# @return [ MapReduce ]
#
# @since 3.0.0
def scope(object)
- @map_reduce = @map_reduce.scope(object)
+ command[:scope] = object
self
end
# Get the execution time of the map/reduce.
#
@@ -238,17 +230,98 @@
finalize: #{command[:finalize]}
out: #{command[:out].inspect}>
}
end
- def command
- @map_reduce.send(:map_reduce_spec)[:selector]
+ private
+
+ # Apply criteria specific options - query, sort, limit.
+ #
+ # @api private
+ #
+ # @example Apply the criteria options
+ # map_reduce.apply_criteria_options
+ #
+ # @return [ nil ] Nothing.
+ #
+ # @since 3.0.0
+ def apply_criteria_options
+ command[:query] = criteria.selector
+ if sort = criteria.options[:sort]
+ command[:sort] = sort
+ end
+ if limit = criteria.options[:limit]
+ command[:limit] = limit
+ end
end
- private
+ # Get the result documents from the map/reduce. If the output was inline
+ # then we grab them from the results key. If the output was a temp
+ # collection then we need to execute a find on that collection.
+ #
+ # @api private
+ #
+ # @example Get the documents.
+ # map_reduce.documents
+ #
+ # @return [ Array, Cursor ] The documents.
+ #
+ # @since 3.0.0
+ def documents
+ return results["results"] if results.has_key?("results")
+ view = client[output_collection].find
+ view.no_cursor_timeout if criteria.options[:timeout] == false
+ view
+ end
- def validate_out!
- raise Errors::NoMapReduceOutput.new({}) unless @map_reduce.out
+ # Get the collection that the map/reduce results were stored in.
+ #
+ # @api private
+ #
+ # @example Get the output collection.
+ # map_reduce.output_collection
+ #
+ # @return [ Symbol, String ] The output collection.
+ #
+ # @since 3.0.0
+ def output_collection
+ command[:out].values.first
+ end
+
+ # Execute the map/reduce command and get the results.
+ #
+ # @api private
+ #
+ # @example Get the results.
+ # map_reduce.results
+ #
+ # @return [ Hash ] The results of the command.
+ #
+ # @since 3.0.0
+ def results
+ raise Errors::NoMapReduceOutput.new(command) unless command[:out]
+ @results ||= __client__.command(command).first
+ end
+
+ # Get the client with the proper consistency.
+ #
+ # @api private
+ #
+ # @note We can use eventual if the output is set to inline.
+ #
+ # @example Get the client.
+ # map_reduce.__client__
+ #
+ # @return [ Mongo::Client ] The client with consistency set.
+ #
+ # @since 3.0.15
+ def __client__
+ if command[:out][:inline] != 1
+ # @todo: close
+ client.with(read: { mode: :primary })
+ else
+ client
+ end
end
end
end
end