Permalink
Browse files

RUBY-564 Support for new (hashed, text, geo2dsphere) index types

  • Loading branch information...
1 parent 6428bf6 commit 26b7ddc78cba2d8ba17988d6514eb497e33125b9 @estolfo estolfo committed Mar 7, 2013
Showing with 60 additions and 18 deletions.
  1. +11 −0 lib/mongo.rb
  2. +23 −16 lib/mongo/collection.rb
  3. +1 −1 lib/mongo/db.rb
  4. +24 −0 test/functional/collection_test.rb
  5. +1 −1 test/unit/collection_test.rb
View
@@ -2,7 +2,18 @@ module Mongo
ASCENDING = 1
DESCENDING = -1
GEO2D = '2d'
+ GEO2DSPHERE = '2dsphere'
GEOHAYSTACK = 'geoHaystack'
+ TEXT = 'text'
+ HASHED = 'hashed'
+ INDEX_TYPES = [ ASCENDING,
+ DESCENDING,
+ GEO2D,
+ GEO2DSPHERE,
+ GEOHAYSTACK,
+ TEXT,
+ HASHED
+ ]
DEFAULT_MAX_BSON_SIZE = 4 * 1024 * 1024
DEFAULT_MAX_MESSAGE_SIZE = DEFAULT_MAX_BSON_SIZE * 2
View
@@ -483,8 +483,9 @@ def update(selector, document, opts={})
#
# @param [String, Array] spec
# should be either a single field name or an array of
- # [field name, direction] pairs. Directions should be specified
- # as Mongo::ASCENDING, Mongo::DESCENDING, or Mongo::GEO2D.
+ # [field name, type] pairs. Index types should be specified
+ # as Mongo::ASCENDING, Mongo::DESCENDING, Mongo::GEO2D, Mongo::GEO2DSPHERE, Mongo::GEOHAYSTACK,
+ # Mongo::TEXT or Mongo::HASHED.
#
# Note that geospatial indexing only works with versions of MongoDB >= 1.3.3+. Keep in mind, too,
# that in order to geo-index a given field, that field must reference either an array or a sub-object
@@ -501,6 +502,8 @@ def update(selector, document, opts={})
# feature is only available in MongoDB >= 1.3.2.
# @option opts [Boolean] :drop_dups (nil) If creating a unique index on a collection with pre-existing records,
# this option will keep the first document the database indexes and drop all subsequent with duplicate values.
+ # @option opts [Integer] :bucket_size (nil) For use with geoHaystack indexes. Number of documents to group
+ # together within a certain proximity to a given longitude and latitude.
# @option opts [Integer] :min (nil) specify the minimum longitude and latitude for a geo index.
# @option opts [Integer] :max (nil) specify the maximum longitude and latitude for a geo index.
#
@@ -525,11 +528,12 @@ def update(selector, document, opts={})
#
# @core indexes create_index-instance_method
def create_index(spec, opts={})
- opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
- field_spec = parse_index_spec(spec)
- opts = opts.dup
- name = opts.delete(:name) || generate_index_name(field_spec)
- name = name.to_s if name
+ opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
+ opts[:bucketSize] = opts[:bucket_size] if opts[:bucket_size]
+ field_spec = parse_index_spec(spec)
+ opts = opts.dup
+ name = opts.delete(:name) || generate_index_name(field_spec)
+ name = name.to_s if name
generate_indexes(field_spec, name, opts)
name
end
@@ -551,11 +555,12 @@ def create_index(spec, opts={})
#
# @return [String] the name of the index.
def ensure_index(spec, opts={})
- now = Time.now.utc.to_i
- opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
- field_spec = parse_index_spec(spec)
- name = opts[:name] || generate_index_name(field_spec)
- name = name.to_s if name
+ now = Time.now.utc.to_i
+ opts[:dropDups] = opts[:drop_dups] if opts[:drop_dups]
+ opts[:bucketSize] = opts[:bucket_size] if opts[:bucket_size]
+ field_spec = parse_index_spec(spec)
+ name = opts[:name] || generate_index_name(field_spec)
+ name = name.to_s if name
if !@cache[name] || @cache[name] <= now
generate_indexes(field_spec, name, opts)
@@ -1017,11 +1022,13 @@ def parse_index_spec(spec)
end
elsif spec.is_a?(Array) && spec.all? {|field| field.is_a?(Array) }
spec.each do |f|
- if [Mongo::ASCENDING, Mongo::DESCENDING, Mongo::GEO2D, Mongo::GEOHAYSTACK].include?(f[1])
+ if Mongo::INDEX_TYPES.include?(f[1])
field_spec[f[0].to_s] = f[1]
else
raise MongoArgumentError, "Invalid index field #{f[1].inspect}; " +
- "should be one of Mongo::ASCENDING (1), Mongo::DESCENDING (-1) or Mongo::GEO2D ('2d')."
+ "should be one of Mongo::ASCENDING (#{Mongo::ASCENDING}), Mongo::DESCENDING (#{Mongo::DESCENDING}), " +
+ "Mongo::GEOHAYSTACK ('#{Mongo::GEOHAYSTACK}'), Mongo::GEO2DSPHERE ('#{Mongo::GEO2DSPHERE}'), " +
+ "Mongo::TEXT ('#{Mongo::TEXT}'), or Mongo::HASHED ('#{Mongo::HASHED}')"
end
end
else
@@ -1109,8 +1116,8 @@ def insert_documents(documents, collection_name=@name, check_keys=true, write_co
def generate_index_name(spec)
indexes = []
- spec.each_pair do |field, direction|
- indexes.push("#{field}_#{direction}")
+ spec.each_pair do |field, type|
+ indexes.push("#{field}_#{type}")
end
indexes.join("_")
end
View
@@ -441,7 +441,7 @@ def drop_index(collection_name, index_name)
#
# @param [String] collection_name
#
- # @return [Hash] keys are index names and the values are lists of [key, direction] pairs
+ # @return [Hash] keys are index names and the values are lists of [key, type] pairs
# defining the index.
def index_information(collection_name)
sel = {:ns => full_collection_name(collection_name)}
@@ -1252,12 +1252,36 @@ def test_max_scan
assert_nil @geo.index_information['baz']
end
+ #should "create a text index" do
+ # @geo.save({'title' => "some text"})
+ # @geo.create_index([['title', Mongo::TEXT]])
+ # assert @geo.index_information['title_text']
+ #end
+
+ should "create a hashed index" do
+ @geo.save({'a' => 1})
+ @geo.create_index([['a', Mongo::HASHED]])
+ assert @geo.index_information['a_hashed']
+ end
+
should "create a geospatial index" do
@geo.save({'loc' => [-100, 100]})
@geo.create_index([['loc', Mongo::GEO2D]])
assert @geo.index_information['loc_2d']
end
+ should "create a geoHaystack index" do
+ @geo.save({ "_id" => 100, "pos" => { "long" => 126.9, "lat" => 35.2 }, "type" => "restaurant"})
+ @geo.create_index([['pos', Mongo::GEOHAYSTACK], ['type', Mongo::ASCENDING]], :bucket_size => 1)
+ puts @geo.index_information['loc_geoHaystack_type_1']
+ end
+
+ should "create a geo 2dsphere index" do
+ @collection.insert({"coordinates" => [ 5 , 5 ], "type" => "Point"})
+ @geo.create_index([['coordinates', Mongo::GEO2DSPHERE]])
+ assert @geo.index_information['coordinates_2dsphere']
+ end
+
should "create a unique index" do
@collection.create_index([['a', Mongo::ASCENDING]], :unique => true)
assert @collection.index_information['a_1']['unique'] == true
@@ -106,7 +106,7 @@ class CollectionTest < Test::Unit::TestCase
@coll.ensure_index [["x", Mongo::DESCENDING]]
end
- should "call generate_indexes for a new direction on the same field for ensure_index" do
+ should "call generate_indexes for a new type on the same field for ensure_index" do
@client = MongoClient.new('localhost', 27017, :logger => @logger, :connect => false)
@db = @client['testing']
@coll = @db.collection('books')

0 comments on commit 26b7ddc

Please sign in to comment.