Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

RUBY-564 Support for (hashed, text, 2dsphere) index types #170

Merged
merged 1 commit into from

3 participants

@estolfo
Collaborator

In Mongo module: Added in constants for hashed, text, and 2dsphere index types. Added array constant for index types.

Added in conversion of bucket_size to bucketSize for use with geoHaystack indexes in the create_index and ensure_index methods on a collection.

Included hashed, text and 2dsphere in the list of valid index types when creating an index.

Wrote tests that ensure 2dsphere, text, geoHaystack, and hashed indexes can be created. NOTE: the test on a text index is commented out because the server must be started with 'setParameter textSearchEnabled=1'

Updated documentation for all affected methods, specifically references to index types as "directions".

@brandonblack

Great work @estolfo. Looks good to me, :shipit:

lib/mongo.rb
((5 lines not shown))
GEOHAYSTACK = 'geoHaystack'
+ TEXT = 'text'
+ HASHED = 'hashed'

We could make these symbols.

Lets make an array of all the possible index types for easier validation.

INDEX_TYPES = [ASCENDING, DESCENDING...]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/mongo/collection.rb
@@ -1017,11 +1022,14 @@ 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::ASCENDING, Mongo::DESCENDING, Mongo::GEO2D, Mongo::GEO2DSPHERE, Mongo::GEOHAYSTACK,
+ Mongo::TEXT, Mongo::HASHED].include?(f[1])
field_spec[f[0].to_s] = f[1]

Mongo::INDEX_TYPES.include?(f[1]) given the above change to add the array is made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/mongo/collection.rb
((7 lines not shown))
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 (1), Mongo::DESCENDING (-1), Mongo::GEO2D ('2d'),
+ Mongo::GEOHAYSTACK ('geoHaystack') or Mongo::GEO2DSPHERE ('2dsphere'), Mongo::TEXT ('text') or
+ Mongo::HASHED ('hashed')."
end

This should be a here doc or a string concatenation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@TylerBrock TylerBrock commented on the diff
lib/mongo/collection.rb
((6 lines not shown))
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}')"

How about "should be one of #{INDEX_TYPES.inspect}"

@estolfo Collaborator
estolfo added a note

that works, but it'll only print out the server index type labels, which might not be very informative in the case of 1 and -1
What do you think?

Users don't need to know what the values of the types are to use this feature. ASCENDING, DESCENDING, etc are 1000x more informative than 1 and -1 in my opinion.

@estolfo Collaborator
estolfo added a note

That's what I'm saying - if you print #{INDEX_TYPES.inspect}, it'll print [1, -1, "2d", "2dsphere", "geoHaystack", "text", "hashed"]
which I don't think is great.

OK, LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@estolfo estolfo merged commit 6b80321 into mongodb:master

1 check passed

Details default The Travis build passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
11 lib/mongo.rb
@@ -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
39 lib/mongo/collection.rb
@@ -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}')"

How about "should be one of #{INDEX_TYPES.inspect}"

@estolfo Collaborator
estolfo added a note

that works, but it'll only print out the server index type labels, which might not be very informative in the case of 1 and -1
What do you think?

Users don't need to know what the values of the types are to use this feature. ASCENDING, DESCENDING, etc are 1000x more informative than 1 and -1 in my opinion.

@estolfo Collaborator
estolfo added a note

That's what I'm saying - if you print #{INDEX_TYPES.inspect}, it'll print [1, -1, "2d", "2dsphere", "geoHaystack", "text", "hashed"]
which I don't think is great.

OK, LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
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
2  lib/mongo/db.rb
@@ -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)}
View
24 test/functional/collection_test.rb
@@ -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
View
2  test/unit/collection_test.rb
@@ -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')
Something went wrong with that request. Please try again.