Moved hint call from Cursor into Collection#find options and Query#initialize
parameter.
This commit is contained in:
parent
086fbaf6e5
commit
b3bc2c41e2
|
@ -23,27 +23,18 @@ module XGen
|
||||||
# A named collection of records in a database.
|
# A named collection of records in a database.
|
||||||
class Collection
|
class Collection
|
||||||
|
|
||||||
attr_reader :db, :name, :hint_fields
|
attr_reader :db, :name, :hint
|
||||||
|
|
||||||
def initialize(db, name)
|
def initialize(db, name)
|
||||||
@db = db
|
@db = db
|
||||||
@name = name
|
@name = name
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set hint fields to use and return +self+. hint_fields may be a
|
# Set hint fields to use and return +self+. hint may be a
|
||||||
# single field name, array of field names, or a hash whose keys will
|
# single field name, array of field names, or a hash whose keys will
|
||||||
# become the hint field names. May be +nil+.
|
# become the hint field names. May be +nil+.
|
||||||
def hint(hint_fields)
|
def hint=(hint)
|
||||||
@hint_fields = case hint_fields
|
@hint = normalize_hint_fields(hint)
|
||||||
when String
|
|
||||||
[hint_fields]
|
|
||||||
when Hash
|
|
||||||
hint_fields.keys
|
|
||||||
when nil
|
|
||||||
nil
|
|
||||||
else
|
|
||||||
hint_fields.to_a
|
|
||||||
end
|
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -57,14 +48,21 @@ module XGen
|
||||||
# :sort :: Either hash of field names as keys and 1/-1 as values; 1 ==
|
# :sort :: Either hash of field names as keys and 1/-1 as values; 1 ==
|
||||||
# ascending, -1 == descending, or array of field names (all
|
# ascending, -1 == descending, or array of field names (all
|
||||||
# assumed to be sorted in ascending order).
|
# assumed to be sorted in ascending order).
|
||||||
|
# :hint :: See #hint. This option overrides the collection-wide value.
|
||||||
def find(selector={}, options={})
|
def find(selector={}, options={})
|
||||||
fields = options.delete(:fields)
|
fields = options.delete(:fields)
|
||||||
fields = nil if fields && fields.empty?
|
fields = nil if fields && fields.empty?
|
||||||
offset = options.delete(:offset) || 0
|
offset = options.delete(:offset) || 0
|
||||||
limit = options.delete(:limit) || 0
|
limit = options.delete(:limit) || 0
|
||||||
sort = options.delete(:sort)
|
sort = options.delete(:sort)
|
||||||
|
hint = options.delete(:hint)
|
||||||
|
if hint
|
||||||
|
hint = normalize_hint_fields(hint)
|
||||||
|
else
|
||||||
|
hint = @hint
|
||||||
|
end
|
||||||
raise RuntimeError, "Unknown options [#{options.inspect}]" unless options.empty?
|
raise RuntimeError, "Unknown options [#{options.inspect}]" unless options.empty?
|
||||||
@db.query(self, Query.new(selector, fields, offset, limit, sort))
|
@db.query(self, Query.new(selector, fields, offset, limit, sort, hint))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Insert +objects+, which are hashes. "<<" is aliased to this method.
|
# Insert +objects+, which are hashes. "<<" is aliased to this method.
|
||||||
|
@ -154,6 +152,20 @@ module XGen
|
||||||
@db.count(@name, selector || {})
|
@db.count(@name, selector || {})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def normalize_hint_fields(hint)
|
||||||
|
case hint
|
||||||
|
when String
|
||||||
|
[hint]
|
||||||
|
when Hash
|
||||||
|
hint.keys
|
||||||
|
when nil
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
hint.to_a
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,24 +42,6 @@ module XGen
|
||||||
|
|
||||||
def closed?; @closed; end
|
def closed?; @closed; end
|
||||||
|
|
||||||
# Set hint fields to use and return +self+. hint_fields may be a
|
|
||||||
# single field name, array of field names, or a hash whose keys will
|
|
||||||
# become the hint field names. May be +nil+. If no hint fields are
|
|
||||||
# specified, the ones in the collection are used if they exist.
|
|
||||||
def hint(hint_fields)
|
|
||||||
@hint_fields = case hint_fields
|
|
||||||
when String
|
|
||||||
[hint_fields]
|
|
||||||
when Hash
|
|
||||||
hint_fields.keys
|
|
||||||
when nil
|
|
||||||
nil
|
|
||||||
else
|
|
||||||
hint_fields.to_a
|
|
||||||
end
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
# Return +true+ if there are more records to retrieve. We do not check
|
# Return +true+ if there are more records to retrieve. We do not check
|
||||||
# @num_to_return; #each is responsible for doing that.
|
# @num_to_return; #each is responsible for doing that.
|
||||||
def more?
|
def more?
|
||||||
|
@ -223,12 +205,8 @@ module XGen
|
||||||
def send_query_if_needed
|
def send_query_if_needed
|
||||||
# Run query first time we request an object from the wire
|
# Run query first time we request an object from the wire
|
||||||
unless @query_run
|
unless @query_run
|
||||||
hints = @hint_fields || @collection.hint_fields
|
|
||||||
old_hints = @query.hint_fields
|
|
||||||
@query.hint_fields = hints
|
|
||||||
@db.send_query_message(QueryMessage.new(@db.name, @collection.name, @query))
|
@db.send_query_message(QueryMessage.new(@db.name, @collection.name, @query))
|
||||||
@query_run = true
|
@query_run = true
|
||||||
@query.hint_fields = old_hints
|
|
||||||
read_all
|
read_all
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,9 +44,9 @@ module XGen
|
||||||
raise "illegal order_by: is a #{query.order_by.class.name}, must be String, Array, Hash, or OrderedHash"
|
raise "illegal order_by: is a #{query.order_by.class.name}, must be String, Array, Hash, or OrderedHash"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if query.hint_fields && query.hint_fields.length > 0
|
if query.hint && query.hint.length > 0
|
||||||
hints = OrderedHash.new
|
hints = OrderedHash.new
|
||||||
query.hint_fields.each { |hf| hints[hf] = 1 }
|
query.hint.each { |hf| hints[hf] = 1 }
|
||||||
sel['$hint'] = hints
|
sel['$hint'] = hints
|
||||||
end
|
end
|
||||||
if query.explain
|
if query.explain
|
||||||
|
|
|
@ -29,7 +29,7 @@ module XGen
|
||||||
# If true, $explain will be set in QueryMessage that uses this query.
|
# If true, $explain will be set in QueryMessage that uses this query.
|
||||||
attr_accessor :explain
|
attr_accessor :explain
|
||||||
# Either +nil+ or an array of hint field names.
|
# Either +nil+ or an array of hint field names.
|
||||||
attr_accessor :hint_fields
|
attr_accessor :hint
|
||||||
attr_reader :selector # writer defined below
|
attr_reader :selector # writer defined below
|
||||||
|
|
||||||
# sel :: A hash describing the query. See the Mongo docs for details.
|
# sel :: A hash describing the query. See the Mongo docs for details.
|
||||||
|
@ -58,8 +58,12 @@ module XGen
|
||||||
# probably will not be what you intend because key order
|
# probably will not be what you intend because key order
|
||||||
# is not preserved. (order_by is called :sort in calls to
|
# is not preserved. (order_by is called :sort in calls to
|
||||||
# Collection#find.)
|
# Collection#find.)
|
||||||
def initialize(sel={}, return_fields=nil, number_to_skip=0, number_to_return=0, order_by=nil)
|
#
|
||||||
@number_to_skip, @number_to_return, @order_by = number_to_skip, number_to_return, order_by
|
# hint :: If not +nil+, specifies query hint fields. See
|
||||||
|
# Collection#hint.
|
||||||
|
def initialize(sel={}, return_fields=nil, number_to_skip=0, number_to_return=0, order_by=nil, hint=nil)
|
||||||
|
@number_to_skip, @number_to_return, @order_by, @hint =
|
||||||
|
number_to_skip, number_to_return, order_by, hint
|
||||||
self.selector = sel
|
self.selector = sel
|
||||||
self.fields = return_fields
|
self.fields = return_fields
|
||||||
end
|
end
|
||||||
|
@ -102,7 +106,7 @@ module XGen
|
||||||
end
|
end
|
||||||
|
|
||||||
def contains_special_fields
|
def contains_special_fields
|
||||||
(@order_by != nil && @order_by.length > 0) || @explain || @hint_fields
|
(@order_by != nil && @order_by.length > 0) || @explain || @hint
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -54,13 +54,4 @@ class CursorTest < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_hint
|
|
||||||
begin
|
|
||||||
cursor = @coll.find('a' => 1).hint('a')
|
|
||||||
assert_equal 1, cursor.to_a.size
|
|
||||||
rescue => ex
|
|
||||||
fail ex.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -372,4 +372,31 @@ class DBAPITest < Test::Unit::TestCase
|
||||||
assert_equal "#{@db.host}:#{@db.port}", @db.master
|
assert_equal "#{@db.host}:#{@db.port}", @db.master
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_hint
|
||||||
|
begin
|
||||||
|
assert_nil @coll.hint
|
||||||
|
assert_equal 1, @coll.find({'a' => 1}, :hint => 'a').to_a.size
|
||||||
|
assert_equal 1, @coll.find({'a' => 1}, :hint => ['a']).to_a.size
|
||||||
|
assert_equal 1, @coll.find({'a' => 1}, :hint => {'a' => 1}).to_a.size
|
||||||
|
|
||||||
|
@coll.hint = 'a'
|
||||||
|
assert_equal ['a'], @coll.hint
|
||||||
|
assert_equal 1, @coll.find('a' => 1).to_a.size
|
||||||
|
|
||||||
|
@coll.hint = ['a']
|
||||||
|
assert_equal ['a'], @coll.hint
|
||||||
|
assert_equal 1, @coll.find('a' => 1).to_a.size
|
||||||
|
|
||||||
|
@coll.hint = {'a' => 1}
|
||||||
|
assert_equal ['a'], @coll.hint
|
||||||
|
assert_equal 1, @coll.find('a' => 1).to_a.size
|
||||||
|
|
||||||
|
@coll.hint = nil
|
||||||
|
assert_nil @coll.hint
|
||||||
|
assert_equal 1, @coll.find('a' => 1).to_a.size
|
||||||
|
rescue => ex
|
||||||
|
fail ex.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue