Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/mongo/collection/view.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ def hash
def initialize(collection, selector = {}, options = {})
validate_doc!(selector)
@collection = collection
@selector = selector.dup
@options = options.dup
setup(selector, options)
end

# Get a human-readable string representation of +View+.
Expand Down
12 changes: 6 additions & 6 deletions lib/mongo/collection/view/immutable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ module Immutable

private

# @api private
#
# @note In the including class, the method #immutable needs to be
# implemented in order to define how a new class of that type needs to
# be instantiated.
def configure(field, value)
return options[field] if value.nil?
new(options.merge(field => value))
new(options.merge(field => value, :modifiers => @modifiers))
end

def configure_modifier(field, value)
return @modifiers[Readable::SPECIAL_FIELDS[field]] if value.nil?
new(options.merge(:modifiers => @modifiers.merge(Readable::SPECIAL_FIELDS[field] => value)))
end

def configure_flag(flag)
Expand Down
8 changes: 6 additions & 2 deletions lib/mongo/collection/view/map_reduce.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,16 @@ def map_reduce_spec
:mapreduce => collection.name,
:map => map,
:reduce => reduce,
:query => view.selector[:$query] || view.selector,
:query => view.modifiers[:$query] || view.selector,
:out => { inline: 1 }
}.merge(options).merge(view.options)
}.merge(options).merge(view_options)
}
end

def view_options
view.sort ? view.options.merge(:sort => view.sort) : view.options
end

def new(options)
MapReduce.new(view, map, reduce, options)
end
Expand Down
113 changes: 60 additions & 53 deletions lib/mongo/collection/view/readable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,23 @@ class View
# @since 2.0.0
module Readable

# Special fields and their getters for the query selector.
# Special fields and their option names for the query selector.
#
# @since 2.0.0
SPECIAL_FIELDS = {
:$query => :selector,
:$readPreference => :read_pref_formatted,
:$orderby => :sort,
:$hint => :hint,
:$comment => :comment,
:$snapshot => :snapshot,
:$maxScan => :max_scan,
:$max => :max_value,
:$min => :min_value,
:$maxTimeMS => :max_time_ms,
:$returnKey => :return_key,
:$showDiskLoc => :show_disk_loc,
:$explain => :explained?
:sort => :$orderby,
:hint => :$hint,
:comment => :$comment,
:snapshot => :$snapshot,
:max_scan => :$maxScan,
:max_value => :$max,
:min_value => :$min,
:max_time_ms => :$maxTimeMS,
:return_key => :$returnKey,
:show_disk_loc => :$showDiskLoc,
:explain => :$explain
}.freeze

# Get just the names of the special fields.
#
# @since 2.1.0
SPECIAL_FIELD_OPTION_NAMES = SPECIAL_FIELDS.values.freeze

# Options to cursor flags mapping.
#
# @since 2.1.0
Expand Down Expand Up @@ -99,7 +92,7 @@ def allow_partial_results
#
# @since 2.0.0
def batch_size(batch_size = nil)
configure(:batch_size, batch_size)
configure(__method__, batch_size)
end

# Associate a comment with the query.
Expand All @@ -117,7 +110,7 @@ def batch_size(batch_size = nil)
#
# @since 2.0.0
def comment(comment = nil)
configure(:comment, comment)
configure_modifier(__method__, comment)
end

# Get a count of matching documents in the collection.
Expand Down Expand Up @@ -181,7 +174,7 @@ def distinct(field_name, options={})
#
# @since 2.0.0
def hint(hint = nil)
configure(:hint, hint)
configure_modifier(__method__, hint)
end

# The max number of docs to return from the query.
Expand All @@ -195,7 +188,7 @@ def hint(hint = nil)
#
# @since 2.0.0
def limit(limit = nil)
configure(:limit, limit)
configure(__method__, limit)
end

# Execute a map/reduce operation on the collection view.
Expand Down Expand Up @@ -225,7 +218,7 @@ def map_reduce(map, reduce, options = {})
#
# @since 2.0.0
def max_scan(value = nil)
configure(:max_scan, value)
configure_modifier(__method__, value)
end

# Set the maximum value to search.
Expand All @@ -239,7 +232,7 @@ def max_scan(value = nil)
#
# @since 2.1.0
def max_value(value = nil)
configure(:max_value, value)
configure_modifier(__method__, value)
end

# Set the minimum value to search.
Expand All @@ -253,7 +246,7 @@ def max_value(value = nil)
#
# @since 2.1.0
def min_value(value = nil)
configure(:min_value, value)
configure_modifier(__method__, value)
end

# The server normally times out idle cursors after an inactivity period
Expand All @@ -266,7 +259,7 @@ def min_value(value = nil)
#
# @since 2.0.0
def no_cursor_timeout
configure_flag(:no_cursor_timeout)
configure_flag(__method__)
end

# The fields to include or exclude from each doc in the result set.
Expand All @@ -285,7 +278,7 @@ def no_cursor_timeout
# @since 2.0.0
def projection(document = nil)
validate_doc!(document) if document
configure(:projection, document)
configure(__method__, document)
end

# The read preference to use for the query.
Expand All @@ -301,7 +294,7 @@ def projection(document = nil)
# @since 2.0.0
def read(value = nil)
return default_read if value.nil?
configure(:read, value.is_a?(Hash) ? ServerSelector.get(value) : value)
configure(__method__, value.is_a?(Hash) ? ServerSelector.get(value) : value)
end

# Set whether to return only the indexed field or fields.
Expand All @@ -315,7 +308,7 @@ def read(value = nil)
#
# @since 2.1.0
def return_key(value = nil)
configure(:return_key, value)
configure_modifier(__method__, value)
end

# Set whether the disk location should be shown for each document.
Expand All @@ -330,7 +323,7 @@ def return_key(value = nil)
#
# @since 2.0.0
def show_disk_loc(value = nil)
configure(:show_disk_loc, value)
configure_modifier(__method__, value)
end

# The number of docs to skip before returning results.
Expand All @@ -345,7 +338,7 @@ def show_disk_loc(value = nil)
#
# @since 2.0.0
def skip(number = nil)
configure(:skip, number)
configure(__method__, number)
end

# Set the snapshot value for the view.
Expand All @@ -360,7 +353,7 @@ def skip(number = nil)
#
# @since 2.0.0
def snapshot(value = nil)
configure(:snapshot, value)
configure_modifier(__method__, value)
end

# The key and direction pairs by which the result set will be sorted.
Expand All @@ -375,7 +368,7 @@ def snapshot(value = nil)
#
# @since 2.0.0
def sort(spec = nil)
configure(:sort, spec)
configure_modifier(__method__, spec)
end

# “meta” operators that let you modify the output or behavior of a query.
Expand All @@ -389,7 +382,8 @@ def sort(spec = nil)
#
# @since 2.1.0
def modifiers(doc = nil)
configure(:modifiers, doc)
return @modifiers if doc.nil?
new(options.merge(__method__ => doc))
end

# A cumulative time limit in milliseconds for processing operations on a cursor.
Expand All @@ -403,7 +397,7 @@ def modifiers(doc = nil)
#
# @since 2.1.0
def max_time_ms(max = nil)
configure(:max_time_ms, max)
configure_modifier(__method__, max)
end

private
Expand All @@ -421,10 +415,6 @@ def flags
end
end

def has_special_fields?
contains_modifiers? || explained? || cluster.sharded?
end

def parallel_scan(cursor_count)
server = read.select_server(cluster)
Operation::ParallelScan.new(
Expand All @@ -441,6 +431,27 @@ def parallel_scan(cursor_count)
end
end

def setup(sel, opts)
setup_options(opts)
setup_selector(sel)
end

def setup_options(opts)
@options = opts ? opts.dup : {}
@modifiers = @options[:modifiers] ? @options.delete(:modifiers).dup : BSON::Document.new
@options.keys.each { |k| @modifiers.merge!(SPECIAL_FIELDS[k] => @options.delete(k)) if SPECIAL_FIELDS[k] }
@options.freeze
end

def setup_selector(sel)
@selector = sel ? sel.dup : {}
if @selector[:$query] || @selector['$query']
@selector.keys.each { |k| @modifiers.merge!(k => @selector.delete(k)) if k[0] == '$' }
end
@modifiers.freeze
@selector.freeze
end

def query_options
{
:project => projection,
Expand All @@ -451,8 +462,12 @@ def query_options
}
end

def requires_special_selector?
!modifiers.empty? || cluster.sharded?
end

def query_spec
sel = has_special_fields? ? special_selector : selector
sel = requires_special_selector? ? special_selector : selector
{ :selector => sel,
:read => read,
:options => query_options,
Expand All @@ -461,26 +476,18 @@ def query_spec
end

def read_pref_formatted
read.to_mongos
@read_formatted ||= read.to_mongos
end

def special_selector
SPECIAL_FIELDS.reduce({}) do |hash, (key, method)|
value = send(method) || (options[:modifiers] && options[:modifiers][key])
hash[key] = value unless value.nil?
hash
end
sel = BSON::Document.new(:$query => selector).merge!(modifiers)
sel[:$readPreference] = read_pref_formatted unless read_pref_formatted.nil?
sel
end

def validate_doc!(doc)
raise Error::InvalidDocument.new unless doc.respond_to?(:keys)
end

def contains_modifiers?
modifiers || options.keys.any? do |key|
SPECIAL_FIELD_OPTION_NAMES.include?(key)
end
end
end
end
end
Expand Down
12 changes: 9 additions & 3 deletions lib/mongo/grid/fs_bucket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,19 @@ def download_to_stream(id, io)
#
# @since 2.1.0
def open_download_stream_by_name(filename, opts = {}, &block)
view = files_collection.find(:filename => filename).projection(_id: 1)
revision = opts.fetch(:revision, -1)
if revision < 0
file_doc = view.sort('uploadDate' => Mongo::Index::DESCENDING).skip(revision.abs - 1).limit(-1).first
skip = revision.abs - 1
sort = { 'uploadDate' => Mongo::Index::DESCENDING }
else
file_doc = view.sort('uploadDate' => Mongo::Index::ASCENDING).skip(revision).limit(-1).first
skip = revision
sort = { 'uploadDate' => Mongo::Index::ASCENDING }
end
file_doc = files_collection.find({ filename: filename} ,
projection: { _id: 1 },
sort: sort,
skip: skip,
limit: -1).first
unless file_doc
raise Error::FileNotFound.new(filename, :filename) unless opts[:revision]
raise Error::InvalidFileRevision.new(filename, opts[:revision])
Expand Down
4 changes: 2 additions & 2 deletions lib/mongo/grid/stream/read.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class Read
# @since 2.1.0
def initialize(fs, options)
@fs = fs
@options = options
@file_id = options[:file_id]
@options = options.dup
@file_id = @options.delete(:file_id)
@open = true
end

Expand Down
2 changes: 1 addition & 1 deletion lib/mongo/protocol/query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ def op_command
def find_command
document = BSON::Document.new
document[:find] = collection
document[:filter] = filter.key?(:$query) ? filter[:$query] : filter
document[:filter] = filter[:$query] ? filter[:$query] : filter
OPTION_MAPPINGS.each do |legacy, option|
document[option] = options[legacy] unless options[legacy].nil?
end
Expand Down
Loading