RUBY-196 tweaks to Collection#ensure_index
This commit is contained in:
parent
d33ddfb8e0
commit
29dfe390c5
@ -382,6 +382,9 @@ module Mongo
|
|||||||
# Also note that it is permissible to create compound indexes that include a geospatial index as
|
# Also note that it is permissible to create compound indexes that include a geospatial index as
|
||||||
# long as the geospatial index comes first.
|
# 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] :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
|
# @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.
|
# 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]
|
opts[:dropDups] = opts.delete(:drop_dups) if opts[:drop_dups]
|
||||||
field_spec = parse_index_spec(spec)
|
field_spec = parse_index_spec(spec)
|
||||||
name = opts.delete(:name) || generate_index_name(field_spec)
|
name = opts.delete(:name) || generate_index_name(field_spec)
|
||||||
|
|
||||||
generate_indexes(field_spec, name, opts)
|
generate_indexes(field_spec, name, opts)
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Calls create_index and sets a flag to not do so again for another X minutes.
|
# 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]
|
# 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)
|
# 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:
|
# @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+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+3min : @posts.ensure_index([['something_else', Mongo::ASCENDING]) -- calls create_index
|
||||||
# Time t+10min : @posts.ensure_index([['subject', Mongo::ASCENDING]) -- calls create_index and resets the 5 minute counter
|
# 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={})
|
def ensure_index(spec, opts={})
|
||||||
valid = BSON::OrderedHash.new
|
valid = BSON::OrderedHash.new
|
||||||
now = Time.now.utc.to_i
|
now = Time.now.utc.to_i
|
||||||
field_spec = parse_index_spec(spec)
|
field_spec = parse_index_spec(spec)
|
||||||
|
|
||||||
|
|
||||||
field_spec.each do |key, value|
|
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
|
timeout = @cache[cache_key] || 0
|
||||||
valid[key] = value if timeout <= now
|
valid[key] = value if timeout <= now
|
||||||
end
|
end
|
||||||
|
|
||||||
name = opts.delete(:name) || generate_index_name(valid)
|
name = opts.delete(:name) || generate_index_name(valid)
|
||||||
generate_indexes(valid, name, opts) if valid.any?
|
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.each {|n| @cache[n] = now + @cache_time}
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
||||||
# Drop a specified index.
|
# Drop a specified index.
|
||||||
#
|
#
|
||||||
# @param [String] name
|
# @param [String] name
|
||||||
#
|
#
|
||||||
# @core indexes
|
# @core indexes
|
||||||
def drop_index(name)
|
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)
|
@db.drop_index(@name, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -459,6 +469,7 @@ module Mongo
|
|||||||
# @core indexes
|
# @core indexes
|
||||||
def drop_indexes
|
def drop_indexes
|
||||||
@cache = {}
|
@cache = {}
|
||||||
|
|
||||||
# Note: calling drop_indexes with no args will drop them all.
|
# Note: calling drop_indexes with no args will drop them all.
|
||||||
@db.drop_index(@name, '*')
|
@db.drop_index(@name, '*')
|
||||||
end
|
end
|
||||||
@ -468,7 +479,6 @@ module Mongo
|
|||||||
@db.drop_collection(@name)
|
@db.drop_collection(@name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Atomically update and return a document using MongoDB's findAndModify command. (MongoDB > 1.3.0)
|
# 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.
|
# @option opts [Hash] :query ({}) a query selector document for matching the desired document.
|
||||||
@ -709,8 +719,7 @@ module Mongo
|
|||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
def parse_index_spec(spec)
|
def parse_index_spec(spec)
|
||||||
field_spec = BSON::OrderedHash.new
|
field_spec = BSON::OrderedHash.new
|
||||||
if spec.is_a?(String) || spec.is_a?(Symbol)
|
if spec.is_a?(String) || spec.is_a?(Symbol)
|
||||||
@ -730,7 +739,7 @@ module Mongo
|
|||||||
end
|
end
|
||||||
field_spec
|
field_spec
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_indexes(field_spec, name, opts)
|
def generate_indexes(field_spec, name, opts)
|
||||||
selector = {
|
selector = {
|
||||||
:name => name,
|
:name => name,
|
||||||
@ -753,7 +762,6 @@ module Mongo
|
|||||||
|
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Sends a Mongo::Constants::OP_INSERT message to the database.
|
# Sends a Mongo::Constants::OP_INSERT message to the database.
|
||||||
# Takes an array of +documents+, an optional +collection_name+, and a
|
# Takes an array of +documents+, an optional +collection_name+, and a
|
||||||
|
@ -565,29 +565,37 @@ class TestCollection < Test::Unit::TestCase
|
|||||||
|
|
||||||
assert_equal 1, x
|
assert_equal 1, x
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def test_ensure_index
|
def test_ensure_index
|
||||||
@@test.drop_indexes
|
@@test.drop_indexes
|
||||||
@@test.insert("x" => "hello world")
|
@@test.insert("x" => "hello world")
|
||||||
assert_equal 1, @@test.index_information.keys.count #default index
|
assert_equal 1, @@test.index_information.keys.count #default index
|
||||||
|
|
||||||
@@test.ensure_index([["x", Mongo::DESCENDING]], {})
|
@@test.ensure_index([["x", Mongo::DESCENDING]], {})
|
||||||
assert_equal 2, @@test.index_information.keys.count
|
assert_equal 2, @@test.index_information.keys.count
|
||||||
assert @@test.index_information.keys.include? "x_-1"
|
assert @@test.index_information.keys.include? "x_-1"
|
||||||
|
|
||||||
@@test.ensure_index([["x", Mongo::ASCENDING]])
|
@@test.ensure_index([["x", Mongo::ASCENDING]])
|
||||||
assert @@test.index_information.keys.include? "x_1"
|
assert @@test.index_information.keys.include? "x_1"
|
||||||
|
|
||||||
@@test.drop_index("x_1")
|
@@test.drop_index("x_1")
|
||||||
assert_equal 2, @@test.index_information.keys.count
|
assert_equal 2, @@test.index_information.keys.count
|
||||||
@@test.drop_index("x_-1")
|
@@test.drop_index("x_-1")
|
||||||
assert_equal 1, @@test.index_information.keys.count
|
assert_equal 1, @@test.index_information.keys.count
|
||||||
|
|
||||||
@@test.ensure_index([["x", Mongo::DESCENDING]], {}) #should work as not cached.
|
@@test.ensure_index([["x", Mongo::DESCENDING]], {}) #should work as not cached.
|
||||||
assert_equal 2, @@test.index_information.keys.count
|
assert_equal 2, @@test.index_information.keys.count
|
||||||
assert @@test.index_information.keys.include? "x_-1"
|
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
|
end
|
||||||
|
|
||||||
context "Grouping" do
|
context "Grouping" do
|
||||||
|
Loading…
Reference in New Issue
Block a user