RUBY-196 tweaks to Collection#ensure_index

This commit is contained in:
Kyle Banker 2010-11-11 17:41:31 -05:00
parent d33ddfb8e0
commit 29dfe390c5
2 changed files with 41 additions and 25 deletions

View File

@ -382,6 +382,9 @@ module Mongo
# Also note that it is permissible to create compound indexes that include a geospatial index as
# long as the geospatial index comes first.
#
# If your code calls create_index frequently, you can use Collection#ensure_index to cache these calls
# and thereby prevent excessive round trips to the database.
#
# @option opts [Boolean] :unique (false) if true, this index will enforce a uniqueness constraint.
# @option opts [Boolean] :background (false) indicate that the index should be built in the background. This
# feature is only available in MongoDB >= 1.3.2.
@ -411,46 +414,53 @@ module Mongo
opts[:dropDups] = opts.delete(:drop_dups) if opts[:drop_dups]
field_spec = parse_index_spec(spec)
name = opts.delete(:name) || generate_index_name(field_spec)
generate_indexes(field_spec, name, opts)
name
end
# Calls create_index and sets a flag to not do so again for another X minutes.
# this time can be specified as an option when initializing a Mongo::Db object as options[:cache_time]
# Any changes to an index will be propogated through regardless of cache time (eg, if you change index direction)
# this time can be specified as an option when initializing a Mongo::DB object as options[:cache_time]
# Any changes to an index will be propogated through regardless of cache time (e.g., a change of index direction)
#
# The parameters and options for this methods are the same as those for Collection#create_index.
#
# @example Call sequence:
# Time t: @posts.ensure_index([['subject', Mongo::ASCENDING]) -- calls create_index and sets the 5 minute cache
# Time t: @posts.ensure_index([['subject', Mongo::ASCENDING]) -- calls create_index and
# sets the 5 minute cache
# Time t+2min : @posts.ensure_index([['subject', Mongo::ASCENDING]) -- doesn't do anything
# Time t+3min : @posts.ensure_index([['something_else', Mongo::ASCENDING]) -- calls create_index and sets 5 minute cache
# Time t+10min : @posts.ensure_index([['subject', Mongo::ASCENDING]) -- calls create_index and resets the 5 minute counter
# Time t+3min : @posts.ensure_index([['something_else', Mongo::ASCENDING]) -- calls create_index
# and sets 5 minute cache
# Time t+10min : @posts.ensure_index([['subject', Mongo::ASCENDING]) -- calls create_index and
# resets the 5 minute counter
#
# @return [String] the name of the index.
def ensure_index(spec, opts={})
valid = BSON::OrderedHash.new
now = Time.now.utc.to_i
field_spec = parse_index_spec(spec)
field_spec.each do |key, value|
cache_key = generate_index_name({key => value}) #bit of a hack.
cache_key = generate_index_name({key => value})
timeout = @cache[cache_key] || 0
valid[key] = value if timeout <= now
end
name = opts.delete(:name) || generate_index_name(valid)
generate_indexes(valid, name, opts) if valid.any?
# I do this here instead of in the above loop in case there were any errors inserting. Best to be safe.
# Reset the cache here in case there are any errors inserting. Best to be safe.
name.each {|n| @cache[n] = now + @cache_time}
name
end
# Drop a specified index.
#
# @param [String] name
#
# @core indexes
def drop_index(name)
@cache[name] = [] # I do this first because there is no harm in clearing the cache.
@cache[name] = nil
@db.drop_index(@name, name)
end
@ -459,6 +469,7 @@ module Mongo
# @core indexes
def drop_indexes
@cache = {}
# Note: calling drop_indexes with no args will drop them all.
@db.drop_index(@name, '*')
end
@ -468,7 +479,6 @@ module Mongo
@db.drop_collection(@name)
end
# Atomically update and return a document using MongoDB's findAndModify command. (MongoDB > 1.3.0)
#
# @option opts [Hash] :query ({}) a query selector document for matching the desired document.
@ -709,8 +719,7 @@ module Mongo
end
private
def parse_index_spec(spec)
field_spec = BSON::OrderedHash.new
if spec.is_a?(String) || spec.is_a?(Symbol)
@ -730,7 +739,7 @@ module Mongo
end
field_spec
end
def generate_indexes(field_spec, name, opts)
selector = {
:name => name,
@ -753,7 +762,6 @@ module Mongo
nil
end
# Sends a Mongo::Constants::OP_INSERT message to the database.
# Takes an array of +documents+, an optional +collection_name+, and a

View File

@ -565,29 +565,37 @@ class TestCollection < Test::Unit::TestCase
assert_equal 1, x
end
def test_ensure_index
@@test.drop_indexes
@@test.insert("x" => "hello world")
assert_equal 1, @@test.index_information.keys.count #default index
@@test.ensure_index([["x", Mongo::DESCENDING]], {})
assert_equal 2, @@test.index_information.keys.count
assert @@test.index_information.keys.include? "x_-1"
@@test.ensure_index([["x", Mongo::ASCENDING]])
assert @@test.index_information.keys.include? "x_1"
@@test.drop_index("x_1")
assert_equal 2, @@test.index_information.keys.count
@@test.drop_index("x_-1")
assert_equal 1, @@test.index_information.keys.count
@@test.ensure_index([["x", Mongo::DESCENDING]], {}) #should work as not cached.
assert_equal 2, @@test.index_information.keys.count
assert @@test.index_information.keys.include? "x_-1"
# Make sure that drop_index expires cache properly
@@test.ensure_index([['a', 1]])
assert @@test.index_information.keys.include?("a_1")
@@test.drop_index("a_1")
assert !@@test.index_information.keys.include?("a_1")
@@test.ensure_index([['a', 1]])
assert @@test.index_information.keys.include?("a_1")
@@test.drop_index("a_1")
end
context "Grouping" do