jmongo 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +43 -0
  3. data/Rakefile +72 -0
  4. data/jmongo.gemspec +84 -6
  5. data/lib/jmongo.rb +6 -14
  6. data/lib/jmongo/collection.rb +196 -114
  7. data/lib/jmongo/connection.rb +39 -13
  8. data/lib/jmongo/cursor.rb +161 -63
  9. data/lib/jmongo/db.rb +119 -30
  10. data/lib/jmongo/exceptions.rb +39 -0
  11. data/lib/jmongo/mongo-2.6.5.gb1.jar +0 -0
  12. data/lib/jmongo/mongo/bson.rb +130 -0
  13. data/lib/jmongo/mongo/collection.rb +185 -0
  14. data/lib/jmongo/mongo/connection.rb +45 -0
  15. data/lib/jmongo/mongo/db.rb +31 -0
  16. data/lib/jmongo/mongo/jmongo.rb +44 -0
  17. data/lib/jmongo/mongo/mongo.rb +98 -0
  18. data/lib/jmongo/mongo/ruby_ext.rb +38 -0
  19. data/lib/jmongo/mongo/utils.rb +136 -0
  20. data/lib/jmongo/version.rb +1 -1
  21. data/test-results.txt +98 -0
  22. data/test/auxillary/1.4_features.rb +166 -0
  23. data/test/auxillary/authentication_test.rb +68 -0
  24. data/test/auxillary/autoreconnect_test.rb +41 -0
  25. data/test/auxillary/fork_test.rb +30 -0
  26. data/test/auxillary/repl_set_auth_test.rb +58 -0
  27. data/test/auxillary/slave_connection_test.rb +36 -0
  28. data/test/auxillary/threaded_authentication_test.rb +101 -0
  29. data/test/bson/binary_test.rb +15 -0
  30. data/test/bson/bson_test.rb +657 -0
  31. data/test/bson/byte_buffer_test.rb +208 -0
  32. data/test/bson/hash_with_indifferent_access_test.rb +38 -0
  33. data/test/bson/json_test.rb +17 -0
  34. data/test/bson/object_id_test.rb +138 -0
  35. data/test/bson/ordered_hash_test.rb +245 -0
  36. data/test/bson/test_helper.rb +46 -0
  37. data/test/bson/timestamp_test.rb +46 -0
  38. data/test/collection_test.rb +933 -0
  39. data/test/connection_test.rb +325 -0
  40. data/test/conversions_test.rb +121 -0
  41. data/test/cursor_fail_test.rb +75 -0
  42. data/test/cursor_message_test.rb +43 -0
  43. data/test/cursor_test.rb +547 -0
  44. data/test/data/empty_data +0 -0
  45. data/test/data/sample_data +0 -0
  46. data/test/data/sample_file.pdf +0 -0
  47. data/test/data/small_data.txt +1 -0
  48. data/test/db_api_test.rb +739 -0
  49. data/test/db_connection_test.rb +15 -0
  50. data/test/db_test.rb +325 -0
  51. data/test/grid_file_system_test.rb +260 -0
  52. data/test/grid_io_test.rb +210 -0
  53. data/test/grid_test.rb +259 -0
  54. data/test/load/thin/config.ru +6 -0
  55. data/test/load/thin/config.yml.template +6 -0
  56. data/test/load/thin/load.rb +24 -0
  57. data/test/load/unicorn/config.ru +6 -0
  58. data/test/load/unicorn/load.rb +23 -0
  59. data/test/load/unicorn/unicorn.rb.template +29 -0
  60. data/test/replica_sets/connect_test.rb +111 -0
  61. data/test/replica_sets/connection_string_test.rb +29 -0
  62. data/test/replica_sets/count_test.rb +36 -0
  63. data/test/replica_sets/insert_test.rb +54 -0
  64. data/test/replica_sets/pooled_insert_test.rb +58 -0
  65. data/test/replica_sets/query_secondaries.rb +109 -0
  66. data/test/replica_sets/query_test.rb +52 -0
  67. data/test/replica_sets/read_preference_test.rb +43 -0
  68. data/test/replica_sets/refresh_test.rb +123 -0
  69. data/test/replica_sets/replication_ack_test.rb +71 -0
  70. data/test/replica_sets/rs_test_helper.rb +27 -0
  71. data/test/safe_test.rb +68 -0
  72. data/test/support/hash_with_indifferent_access.rb +186 -0
  73. data/test/support/keys.rb +45 -0
  74. data/test/support_test.rb +19 -0
  75. data/test/test_helper.rb +111 -0
  76. data/test/threading/threading_with_large_pool_test.rb +90 -0
  77. data/test/threading_test.rb +88 -0
  78. data/test/tools/auth_repl_set_manager.rb +14 -0
  79. data/test/tools/keyfile.txt +1 -0
  80. data/test/tools/repl_set_manager.rb +377 -0
  81. data/test/unit/collection_test.rb +128 -0
  82. data/test/unit/connection_test.rb +85 -0
  83. data/test/unit/cursor_test.rb +127 -0
  84. data/test/unit/db_test.rb +96 -0
  85. data/test/unit/grid_test.rb +51 -0
  86. data/test/unit/node_test.rb +73 -0
  87. data/test/unit/pool_manager_test.rb +47 -0
  88. data/test/unit/pool_test.rb +9 -0
  89. data/test/unit/read_test.rb +101 -0
  90. data/test/unit/safe_test.rb +125 -0
  91. data/test/uri_test.rb +92 -0
  92. metadata +170 -99
  93. data/lib/jmongo/ajrb.rb +0 -189
  94. data/lib/jmongo/jmongo_jext.rb +0 -302
  95. data/lib/jmongo/mongo-2.6.3.jar +0 -0
  96. data/lib/jmongo/utils.rb +0 -61
@@ -0,0 +1,98 @@
1
+ module Mongo
2
+ ASCENDING = 1
3
+ DESCENDING = -1
4
+ GEO2D = '2d'
5
+
6
+ DEFAULT_MAX_BSON_SIZE = 1024 * 1024 * 4
7
+
8
+ REPLACE = JMongo::MapReduceCommand::OutputType::REPLACE
9
+ MERGE = JMongo::MapReduceCommand::OutputType::MERGE
10
+ REDUCE = JMongo::MapReduceCommand::OutputType::REDUCE
11
+ INLINE = JMongo::MapReduceCommand::OutputType::INLINE
12
+
13
+ MapReduceEnumHash = {:replace => REPLACE, :merge => MERGE, :reduce => REDUCE, :inline => INLINE}
14
+
15
+ DEFAULT_BATCH_SIZE = 100
16
+
17
+ OP_REPLY = 1
18
+ OP_MSG = 1000
19
+ OP_UPDATE = 2001
20
+ OP_INSERT = 2002
21
+ OP_QUERY = 2004
22
+ OP_GET_MORE = 2005
23
+ OP_DELETE = 2006
24
+ OP_KILL_CURSORS = 2007
25
+
26
+ OP_QUERY_TAILABLE = JMongo::Bytes::QUERYOPTION_TAILABLE
27
+ OP_QUERY_SLAVE_OK = JMongo::Bytes::QUERYOPTION_SLAVEOK
28
+ OP_QUERY_OPLOG_REPLAY = JMongo::Bytes::QUERYOPTION_OPLOGREPLAY
29
+ OP_QUERY_NO_CURSOR_TIMEOUT = JMongo::Bytes::QUERYOPTION_NOTIMEOUT
30
+ OP_QUERY_AWAIT_DATA = JMongo::Bytes::QUERYOPTION_AWAITDATA
31
+ OP_QUERY_EXHAUST = JMongo::Bytes::QUERYOPTION_EXHAUST
32
+
33
+ REPLY_CURSOR_NOT_FOUND = JMongo::Bytes::RESULTFLAG_CURSORNOTFOUND
34
+ REPLY_QUERY_FAILURE = JMongo::Bytes::RESULTFLAG_ERRSET
35
+ REPLY_SHARD_CONFIG_STALE = JMongo::Bytes::RESULTFLAG_SHARDCONFIGSTALE
36
+ REPLY_AWAIT_CAPABLE = JMongo::Bytes::RESULTFLAG_AWAITCAPABLE
37
+
38
+ def self.logger(logger=nil)
39
+ logger ? @logger = logger : @logger
40
+ end
41
+
42
+ def self.result_ok?(result)
43
+ result['ok'] == 1.0 || result['ok'] == true
44
+ end
45
+
46
+ # Simple class for comparing server versions.
47
+ class ServerVersion
48
+ include Comparable
49
+
50
+ def initialize(version)
51
+ @version = version
52
+ end
53
+
54
+ # Implements comparable.
55
+ def <=>(new)
56
+ local, new = self.to_a, to_array(new)
57
+ for n in 0...local.size do
58
+ break if elements_include_mods?(local[n], new[n])
59
+ if local[n] < new[n].to_i
60
+ result = -1
61
+ break;
62
+ elsif local[n] > new[n].to_i
63
+ result = 1
64
+ break;
65
+ end
66
+ end
67
+ result || 0
68
+ end
69
+
70
+ # Return an array representation of this server version.
71
+ def to_a
72
+ to_array(@version)
73
+ end
74
+
75
+ # Return a string representation of this server version.
76
+ def to_s
77
+ @version
78
+ end
79
+
80
+ private
81
+
82
+ # Returns true if any elements include mod symbols (-, +)
83
+ def elements_include_mods?(*elements)
84
+ elements.any? { |n| n =~ /[\-\+]/ }
85
+ end
86
+
87
+ # Converts argument to an array of integers,
88
+ # appending any mods as the final element.
89
+ def to_array(version)
90
+ array = version.split(".").map {|n| (n =~ /^\d+$/) ? n.to_i : n }
91
+ if array.last =~ /(\d+)([\-\+])/
92
+ array[array.length-1] = $1.to_i
93
+ array << $2
94
+ end
95
+ array
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,38 @@
1
+
2
+ class String
3
+ def to_bson_code
4
+ BSON::Code.new(self)
5
+ end
6
+ end
7
+
8
+ class Symbol
9
+ def to_bson
10
+ BSON::Symbol.new(self.to_s)
11
+ end
12
+ end
13
+
14
+ class Object
15
+ def to_bson
16
+ self
17
+ end
18
+ end
19
+
20
+ class Hash
21
+ def to_bson
22
+ obj = ::JMongo::BasicDBObject.new
23
+ self.each_pair do |key, val|
24
+ obj.put( key.to_s, val.to_bson )
25
+ end
26
+ obj
27
+ end
28
+ end
29
+
30
+ class Array
31
+ def to_bson
32
+ list = Array.new #Java::ComMongodb::DBObject[ary.length].new
33
+ self.each_with_index do |ele, i|
34
+ list[i] = ele.to_bson
35
+ end
36
+ list
37
+ end
38
+ end
@@ -0,0 +1,136 @@
1
+ # Copyright (C) 2010 Guy Boertje
2
+
3
+ module Mongo
4
+ module JavaImpl
5
+
6
+ module NoImplYetClass
7
+ def raise_not_implemented
8
+ raise NoMethodError, "This method hasn't been implemented yet."
9
+ end
10
+ end
11
+
12
+ module Utils
13
+ def raise_not_implemented
14
+ raise NoMethodError, "This method hasn't been implemented yet."
15
+ end
16
+
17
+ def trap_raise(ex_class, msg=nil)
18
+ begin
19
+ yield
20
+ rescue => ex
21
+ raise ex_class, msg ? "#{msg} - #{ex.message}" : ex.message
22
+ end
23
+ end
24
+
25
+ def prep_fields(fields)
26
+ case fields
27
+ when String, Symbol
28
+ {fields => 1}
29
+ when Array
30
+ fields << "_id" if fields.empty?
31
+ Hash[fields.zip( [1]*fields.size )]
32
+ when Hash
33
+ fields
34
+ end
35
+ end
36
+
37
+ def prep_sort(key_or_list=nil, direction=nil)
38
+ return if key_or_list.nil?
39
+ if !direction.nil?
40
+ order = [[key_or_list, direction]]
41
+ elsif key_or_list.is_a?(String) || key_or_list.is_a?(Symbol)
42
+ order = [[key_or_list.to_s, 1]]
43
+ else
44
+ order = [key_or_list]
45
+ end
46
+ hord = {}
47
+ order.flatten.each_slice(2){|k,v| hord[k] = sort_value(k,v)}
48
+ to_dbobject(hord)
49
+ end
50
+
51
+ def to_dbobject obj
52
+ if obj.respond_to?('to_bson')
53
+ obj.to_bson
54
+ elsif obj.respond_to?(:merge)
55
+ hash_to_dbobject(obj)
56
+ elsif obj.respond_to?(:compact)
57
+ array_to_dblist(obj)
58
+ else
59
+ obj
60
+ end
61
+ end
62
+
63
+ def from_dbobject obj
64
+ # for better upstream compatibility make the objects into ruby hash or array
65
+
66
+ case obj
67
+ when Java::ComMongodb::BasicDBObject, Java::ComMongodb::CommandResult
68
+ h = obj.hashify
69
+ Hash[h.keys.zip(h.values.map{|v| from_dbobject(v)})]
70
+ when Java::ComMongodb::BasicDBList
71
+ obj.arrayify.map{|v| from_dbobject(v)}
72
+ when Java::JavaUtil::ArrayList
73
+ obj.map{|v| from_dbobject(v)}
74
+ when Java::JavaUtil::Date
75
+ Time.at(obj.get_time/1000.0)
76
+ when Java::OrgBsonTypes::Symbol
77
+ obj.toString.to_sym
78
+ else
79
+ obj
80
+ end
81
+ end
82
+
83
+ def sort_value(key, value)
84
+ val = value.to_s.downcase
85
+ return val if val == '2d'
86
+ direction = SortingHash[val]
87
+ return direction if direction != 0
88
+ raise InvalidSortValueError.new(
89
+ "for key: #{key}, #{value} was supplied as a sort direction when acceptable values are: " +
90
+ "Mongo::ASCENDING, 'ascending', 'asc', :ascending, :asc, 1, Mongo::DESCENDING, " +
91
+ "'descending', 'desc', :descending, :desc, -1.")
92
+ end
93
+
94
+ SortingHash = Hash.new(0).merge!(
95
+ "ascending" => 1, "asc" => 1, "1" => 1,
96
+ "descending" => -1, "desc" => -1, "-1" => -1
97
+ )
98
+
99
+ private
100
+
101
+ def hash_to_dbobject doc
102
+ obj = JMongo::BasicDBObject.new
103
+ doc.each_pair do |key, value|
104
+ obj.put(key.to_s, to_dbobject(value))
105
+ end
106
+ obj
107
+ end
108
+
109
+ def array_to_dblist ary
110
+ list = [] #Java::ComMongodb::DBObject[ary.length].new
111
+ ary.each_with_index do |ele, i|
112
+ list[i] = to_dbobject(ele)
113
+ end
114
+ list
115
+ end
116
+
117
+ #@collection.save({:doc => 'foo'}, :safe => nil) ---> NONE = new WriteConcern(-1)
118
+ #@collection.save({:doc => 'foo'}, :safe => true) ---> NORMAL = new WriteConcern(0)
119
+ #@collection.save({:doc => 'foo'}, :safe => {:w => 2}) ---> new WriteConcern( 2 , 0 , false)
120
+ #@collection.save({:doc => 'foo'}, :safe => {:w => 2, :wtimeout => 200}) ---> new WriteConcern( 2 , 200 , false)
121
+ #@collection.save({:doc => 'foo'}, :safe => {:w => 2, :wtimeout => 200, :fsync => true}) ---> new WriteConcern( 2 , 0 , true)
122
+ #@collection.save({:doc => 'foo'}, :safe => {:fsync => true}) ---> FSYNC_SAFE = new WriteConcern( 1 , 0 , true)
123
+
124
+ def write_concern(safe)
125
+ return JMongo::WriteConcern.new(-1) if safe.nil?
126
+ return JMongo::WriteConcern.new(0) if safe.is_a?(FalseClass)
127
+ return JMongo::WriteConcern.new(1) if safe.is_a?(TrueClass)
128
+ return JMongo::WriteConcern.new(0) unless safe.is_a?(Hash)
129
+ w = safe[:w] || 1
130
+ t = safe[:wtimeout] || 0
131
+ f = !!(safe[:fsync] || false)
132
+ JMongo::WriteConcern.new(w, t, f) #dont laugh!
133
+ end
134
+ end
135
+ end
136
+ end
@@ -1,3 +1,3 @@
1
1
  module Mongo
2
- VERSION = '1.0.3'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -0,0 +1,98 @@
1
+ Loaded suite ./test/collection_test
2
+ Started
3
+ "test_map_reduce_with_raw_response"
4
+ "function() { emit(this.user_id, 1); }"
5
+ "function(k,vals) { return 1; }"
6
+ {
7
+ "result" => "foo",
8
+ "timeMillis" => 18,
9
+ "timing" => {
10
+ "mapTime" => 0,
11
+ "emitLoop" => 17,
12
+ "total" => 18
13
+ },
14
+ "counts" => {
15
+ "input" => 3,
16
+ "emit" => 3,
17
+ "output" => 3
18
+ },
19
+ "ok" => 1.0
20
+ }
21
+ ........."test_map_reduce_with_output_collection"
22
+ "function() { emit(this.user_id, 1); }"
23
+ "function(k,vals) { return 1; }"
24
+ {
25
+ "result" => "test-map-coll",
26
+ "timeMillis" => 1,
27
+ "timing" => {
28
+ "mapTime" => 0,
29
+ "emitLoop" => 0,
30
+ "total" => 1
31
+ },
32
+ "counts" => {
33
+ "input" => 3,
34
+ "emit" => 3,
35
+ "output" => 3
36
+ },
37
+ "ok" => 1.0
38
+ }
39
+ ....."test_map_reduce_with_code_objects"
40
+ "function() { emit(this.user_id, 1); }"
41
+ "function(k,vals) { return 1; }"
42
+ {
43
+ "result" => "foo",
44
+ "timeMillis" => 1,
45
+ "timing" => {
46
+ "mapTime" => 0,
47
+ "emitLoop" => 0,
48
+ "total" => 1
49
+ },
50
+ "counts" => {
51
+ "input" => 2,
52
+ "emit" => 2,
53
+ "output" => 2
54
+ },
55
+ "ok" => 1.0
56
+ }
57
+ ..."test_map_reduce_with_options"
58
+ "function() { emit(this.user_id, 1); }"
59
+ "function(k,vals) { return 1; }"
60
+ {
61
+ "result" => "foo",
62
+ "timeMillis" => 1,
63
+ "timing" => {
64
+ "mapTime" => 0,
65
+ "emitLoop" => 0,
66
+ "total" => 1
67
+ },
68
+ "counts" => {
69
+ "input" => 2,
70
+ "emit" => 2,
71
+ "output" => 2
72
+ },
73
+ "ok" => 1.0
74
+ }
75
+ .."test_map_reduce"
76
+ "function() { emit(this.user_id, 1); }"
77
+ "function(k,vals) { return 1; }"
78
+ {
79
+ "result" => "foo",
80
+ "timeMillis" => 1,
81
+ "timing" => {
82
+ "mapTime" => 0,
83
+ "emitLoop" => 0,
84
+ "total" => 1
85
+ },
86
+ "counts" => {
87
+ "input" => 2,
88
+ "emit" => 2,
89
+ "output" => 2
90
+ },
91
+ "ok" => 1.0
92
+ }
93
+ ..............
94
+ Finished in 0.304000 seconds.
95
+
96
+ 33 tests, 94 assertions, 0 failures, 0 errors, 0 skips
97
+
98
+ Test run options: --seed 45344
@@ -0,0 +1,166 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require './test/test_helper'
5
+
6
+ # Demonstrate features in MongoDB 1.4
7
+ class Features14Test < Test::Unit::TestCase
8
+
9
+ context "MongoDB 1.4" do
10
+ setup do
11
+ @con = Mongo::Connection.new
12
+ @db = @con['mongo-ruby-test']
13
+ @col = @db['new-features']
14
+ end
15
+
16
+ teardown do
17
+ @col.drop
18
+ end
19
+
20
+ context "new query operators: " do
21
+
22
+ context "$elemMatch: " do
23
+ setup do
24
+ @col.save({:user => 'bob', :updates => [{:date => Time.now.utc, :body => 'skiing', :n => 1},
25
+ {:date => Time.now.utc, :body => 'biking', :n => 2}]})
26
+
27
+ @col.save({:user => 'joe', :updates => [{:date => Time.now.utc, :body => 'skiing', :n => 2},
28
+ {:date => Time.now.utc, :body => 'biking', :n => 10}]})
29
+ end
30
+
31
+ should "match a document with a matching object element in an array" do
32
+ doc = @col.find_one({"updates" => {"$elemMatch" => {"body" => "skiing", "n" => 2}}})
33
+ assert_equal 'joe', doc['user']
34
+ end
35
+
36
+ should "$elemMatch with a conditional operator" do
37
+ doc1 = @col.find_one({"updates" => {"$elemMatch" => {"body" => "biking", "n" => {"$gt" => 5}}}})
38
+ assert_equal 'joe', doc1['user']
39
+ end
40
+
41
+ should "note the difference between $elemMatch and a traditional match" do
42
+ doc = @col.find({"updates.body" => "skiing", "updates.n" => 2}).to_a
43
+ assert_equal 2, doc.size
44
+ end
45
+ end
46
+
47
+ context "$all with regexes" do
48
+ setup do
49
+ @col.save({:n => 1, :a => 'whale'})
50
+ @col.save({:n => 2, :a => 'snake'})
51
+ end
52
+
53
+ should "match multiple regexes" do
54
+ doc = @col.find({:a => {'$all' => [/ha/, /le/]}}).to_a
55
+ assert_equal 1, doc.size
56
+ assert_equal 1, doc.first['n']
57
+ end
58
+
59
+ should "not match if not every regex matches" do
60
+ doc = @col.find({:a => {'$all' => [/ha/, /sn/]}}).to_a
61
+ assert_equal 0, doc.size
62
+ end
63
+ end
64
+
65
+ context "the $not operator" do
66
+ setup do
67
+ @col.save({:a => ['x']})
68
+ @col.save({:a => ['x', 'y']})
69
+ @col.save({:a => ['x', 'y', 'z']})
70
+ end
71
+
72
+ should "negate a standard operator" do
73
+ results = @col.find({:a => {'$not' => {'$size' => 2}}}).to_a
74
+ assert_equal 2, results.size
75
+ results = results.map {|r| r['a']}
76
+ assert_equal ['x'], results.sort.first
77
+ assert_equal ['x', 'y', 'z'], results.sort.last
78
+ end
79
+ end
80
+ end
81
+
82
+ context "new update operators: " do
83
+
84
+ context "$addToSet (pushing a unique value)" do
85
+ setup do
86
+ @col.save({:username => 'bob', :interests => ['skiing', 'guitar']})
87
+ end
88
+
89
+ should "add an item to a set uniquely ($addToSet)" do
90
+ @col.update({:username => 'bob'}, {'$addToSet' => {'interests' => 'skiing'}})
91
+ @col.update({:username => 'bob'}, {'$addToSet' => {'interests' => 'kayaking'}})
92
+ document = @col.find_one({:username => 'bob'})
93
+ assert_equal ['guitar', 'kayaking', 'skiing'], document['interests'].sort
94
+ end
95
+
96
+ should "add an array of items uniquely ($addToSet with $each)" do
97
+ @col.update({:username => 'bob'}, {'$addToSet' => {'interests' => {'$each' => ['skiing', 'kayaking', 'biking']}}})
98
+ document = @col.find_one({:username => 'bob'})
99
+ assert_equal ['biking', 'guitar', 'kayaking', 'skiing'], document['interests'].sort
100
+ end
101
+ end
102
+
103
+ context "the positional operator ($)" do
104
+ setup do
105
+ @id1 = @col.insert({:text => 'hello',
106
+ :comments => [{'by' => 'bob',
107
+ 'text' => 'lol!'},
108
+ {'by' => 'susie',
109
+ 'text' => 'bye bye!'}]})
110
+ @id2 = @col.insert({:text => 'goodbye',
111
+ :comments => [{'by' => 'bob',
112
+ 'text' => 'au revoir'},
113
+ {'by' => 'susie',
114
+ 'text' => 'bye bye!'}]})
115
+ end
116
+
117
+ should "update a matching array item" do
118
+ @col.update({"_id" => @id1, "comments.by" => 'bob'}, {'$set' => {'comments.$.text' => 'lmao!'}}, :multi => true)
119
+ result = @col.find_one({"_id" => @id1})
120
+ assert_equal 'lmao!', result['comments'][0]['text']
121
+ end
122
+ end
123
+ end
124
+
125
+ context "Geoindexing" do
126
+ setup do
127
+ @places = @db['places']
128
+ @places.create_index([['loc', Mongo::GEO2D]])
129
+
130
+ @empire_state = ([40.748371, -73.985031])
131
+ @jfk = ([40.643711, -73.790009])
132
+
133
+ @places.insert({'name' => 'Empire State Building', 'loc' => ([40.748371, -73.985031])})
134
+ @places.insert({'name' => 'Flatiron Building', 'loc' => ([40.741581, -73.987549])})
135
+ @places.insert({'name' => 'Grand Central', 'loc' => ([40.751678, -73.976562])})
136
+ @places.insert({'name' => 'Columbia University', 'loc' => ([40.808922, -73.961617])})
137
+ @places.insert({'name' => 'NYSE', 'loc' => ([40.71455, -74.007124])})
138
+ @places.insert({'name' => 'JFK', 'loc' => ([40.643711, -73.790009])})
139
+ end
140
+
141
+ teardown do
142
+ @places.drop
143
+ end
144
+
145
+ should "find the nearest addresses" do
146
+ results = @places.find({'loc' => {'$near' => @empire_state}}).limit(2).to_a
147
+ assert_equal 2, results.size
148
+ assert_equal 'Empire State Building', results[0]['name']
149
+ assert_equal 'Flatiron Building', results[1]['name']
150
+ end
151
+
152
+ should "use geoNear command to return distances from a point" do
153
+ cmd = BSON::OrderedHash.new
154
+ cmd['geoNear'] = 'places'
155
+ cmd['near'] = @empire_state
156
+ cmd['num'] = 6
157
+ r = @db.command(cmd)
158
+
159
+ assert_equal 6, r['results'].length
160
+ r['results'].each do |result|
161
+ puts result.inspect
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end