mongo 0.17.1 → 0.18

Sign up to get free protection for your applications and to get access to all the features.
@@ -27,8 +27,17 @@ module Mongo
27
27
  # Raised when invalid arguments are sent to Mongo Ruby methods.
28
28
  class MongoArgumentError < MongoRubyError; end
29
29
 
30
+ # Raised on failures in connection to the database server.
31
+ class ConnectionError < MongoRubyError; end
32
+
33
+ # Raised on failures in connection to the database server.
34
+ class ConnectionTimeoutError < MongoRubyError; end
35
+
30
36
  # Raised when a database operation fails.
31
37
  class OperationFailure < MongoDBError; end
38
+
39
+ # Raised when a database operation fails.
40
+ class ConnectionFailure < MongoDBError; end
32
41
 
33
42
  # Raised when a client attempts to perform an invalid operation.
34
43
  class InvalidOperation < MongoDBError; end
@@ -442,7 +442,7 @@ module GridFS
442
442
  md5_command = OrderedHash.new
443
443
  md5_command['filemd5'] = @files_id
444
444
  md5_command['root'] = @root
445
- h['md5'] = @db.db_command(md5_command)['md5']
445
+ h['md5'] = @db.command(md5_command)['md5']
446
446
  h
447
447
  end
448
448
 
@@ -19,7 +19,7 @@ module Mongo #:nodoc:
19
19
  # objects to mongo-friendly parameters.
20
20
  module Conversions
21
21
 
22
- ASCENDING = ["ascending", "asc", "1"]
22
+ ASCENDING = ["ascending", "asc", "1"]
23
23
  DESCENDING = ["descending", "desc", "-1"]
24
24
 
25
25
  # Converts the supplied +Array+ to a +Hash+ to pass to mongo as
@@ -28,17 +28,9 @@ module Mongo #:nodoc:
28
28
  #
29
29
  # Example:
30
30
  #
31
- # *DEPRECATED
32
- #
33
- # <tt>array_as_sort_parameters(["field1", "field2"])</tt> =>
34
- # <tt>{ "field1" => "1", "field2" => "1" }</tt>
35
- #
36
- # *New Syntax:
37
- #
38
31
  # <tt>array_as_sort_parameters([["field1", :asc], ["field2", :desc]])</tt> =>
39
32
  # <tt>{ "field1" => 1, "field2" => -1}</tt>
40
33
  def array_as_sort_parameters(value)
41
- warn_if_deprecated(value)
42
34
  order_by = OrderedHash.new
43
35
  value.each do |param|
44
36
  if (param.class.name == "String")
@@ -50,7 +42,7 @@ module Mongo #:nodoc:
50
42
  order_by
51
43
  end
52
44
 
53
- # Converts the supplied +String+ to a +Hash+ to pass to mongo as
45
+ # Converts the supplied +String+ or +Symbol+ to a +Hash+ to pass to mongo as
54
46
  # a sorting parameter with ascending order. If the +String+
55
47
  # is empty then an empty +Hash+ will be returned.
56
48
  #
@@ -61,22 +53,8 @@ module Mongo #:nodoc:
61
53
  # <tt>string_as_sort_parameters("field")</tt> => <tt>{ "field" => 1 }</tt>
62
54
  # <tt>string_as_sort_parameters("")</tt> => <tt>{}</tt>
63
55
  def string_as_sort_parameters(value)
64
- warn_if_deprecated(value)
65
- return {} if value.empty?
66
- { value => 1 }
67
- end
68
-
69
- # Converts the supplied +Symbol+ to a +Hash+ to pass to mongo as
70
- # a sorting parameter with ascending order.
71
- #
72
- # Example:
73
- #
74
- # *DEPRECATED
75
- #
76
- # <tt>symbol_as_sort_parameters(:field)</tt> => <tt>{ "field" => 1 }</tt>
77
- def symbol_as_sort_parameters(value)
78
- warn_if_deprecated(value)
79
- { value.to_s => 1 }
56
+ return {} if (str = value.to_s).empty?
57
+ { str => 1 }
80
58
  end
81
59
 
82
60
  # Converts the +String+, +Symbol+, or +Integer+ to the
@@ -96,15 +74,5 @@ module Mongo #:nodoc:
96
74
  "#{self} was supplied as a sort direction when acceptable values are: " +
97
75
  "Mongo::ASCENDING, 'ascending', 'asc', :ascending, :asc, 1, Mongo::DESCENDING, 'descending', 'desc', :descending, :desc, -1.")
98
76
  end
99
-
100
- # This is the method to call when the client needs to be warned of
101
- # deprecation in the way sorting parameters are supplied.
102
- def warn_if_deprecated(value)
103
- unless value.is_a?(Array) && value.first.is_a?(Array)
104
- warn("Specifying sort order as #{value.inspect} has been deprecated in favor of a new syntax: \n" +
105
- " :sort => [['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]")
106
- end
107
- end
108
-
109
77
  end
110
78
  end
@@ -0,0 +1,34 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require 'test/test_helper'
5
+
6
+ # NOTE: this test should be run only if a replica pair is running.
7
+ class ReplicaPairCountTest < Test::Unit::TestCase
8
+ include Mongo
9
+
10
+ def setup
11
+ @conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil)
12
+ @db = @conn.db('mongo-ruby-test')
13
+ @db.drop_collection("test-pairs")
14
+ @coll = @db.collection("test-pairs")
15
+ end
16
+
17
+ def test_correct_count_after_insertion_reconnect
18
+ @coll.insert({:a => 20}, :safe => true)
19
+ assert_equal 1, @coll.count
20
+
21
+ # Sleep to allow resync
22
+ sleep(3)
23
+
24
+ puts "Please disconnect the current master."
25
+ gets
26
+
27
+ rescue_connection_failure do
28
+ @coll.insert({:a => 30}, :safe => true)
29
+ end
30
+ @coll.insert({:a => 40}, :safe => true)
31
+ assert_equal 3, @coll.count, "Second count failed"
32
+ end
33
+
34
+ end
@@ -0,0 +1,50 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require 'test/test_helper'
5
+
6
+ # NOTE: this test should be run only if a replica pair is running.
7
+ class ReplicaPairInsertTest < Test::Unit::TestCase
8
+ include Mongo
9
+
10
+ def setup
11
+ @conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil)
12
+ @db = @conn.db('mongo-ruby-test')
13
+ @db.drop_collection("test-pairs")
14
+ @coll = @db.collection("test-pairs")
15
+ end
16
+
17
+ def test_insert
18
+ @coll.save({:a => 20}, :safe => true)
19
+ puts "Please disconnect the current master."
20
+ gets
21
+
22
+ rescue_connection_failure do
23
+ @coll.save({:a => 30}, :safe => true)
24
+ end
25
+
26
+ @coll.save({:a => 40}, :safe => true)
27
+ @coll.save({:a => 50}, :safe => true)
28
+ @coll.save({:a => 60}, :safe => true)
29
+ @coll.save({:a => 70}, :safe => true)
30
+
31
+ puts "Please reconnect the old master to make sure that the new master " +
32
+ "has synced with the previous master. Note: this may have happened already."
33
+ gets
34
+ results = []
35
+
36
+ rescue_connection_failure do
37
+ @coll.find.each {|r| results << r}
38
+ [20, 30, 40, 50, 60, 70].each do |a|
39
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
40
+ end
41
+ end
42
+
43
+ @coll.save({:a => 80}, :safe => true)
44
+ @coll.find.each {|r| results << r}
45
+ [20, 30, 40, 50, 60, 70, 80].each do |a|
46
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a} on second find"
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,54 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require 'test/test_helper'
5
+
6
+ # NOTE: this test should be run only if a replica pair is running.
7
+ class ReplicaPairPooledInsertTest < Test::Unit::TestCase
8
+ include Mongo
9
+
10
+ def setup
11
+ @conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil, :pool_size => 10, :timeout => 5)
12
+ @db = @conn.db('mongo-ruby-test')
13
+ @db.drop_collection("test-pairs")
14
+ @coll = @db.collection("test-pairs")
15
+ end
16
+
17
+ def test_insert
18
+ expected_results = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
19
+ @coll.save({:a => -1}, :safe => true)
20
+ puts "Please disconnect the current master."
21
+ gets
22
+
23
+ threads = []
24
+ 10.times do |i|
25
+ threads[i] = Thread.new do
26
+ rescue_connection_failure do
27
+ @coll.save({:a => i}, :safe => true)
28
+ end
29
+ end
30
+ end
31
+
32
+ puts "Please reconnect the old master to make sure that the new master " +
33
+ "has synced with the previous master. Note: this may have happened already." +
34
+ "Note also that when connection with multiple threads, you may need to wait a few seconds" +
35
+ "after restarting the old master so that all the data has had a chance to sync." +
36
+ "This is a case of eventual consistency."
37
+ gets
38
+ results = []
39
+
40
+ rescue_connection_failure do
41
+ @coll.find.each {|r| results << r}
42
+ expected_results.each do |a|
43
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
44
+ end
45
+ end
46
+
47
+ @coll.save({:a => 10}, :safe => true)
48
+ @coll.find.each {|r| results << r}
49
+ (expected_results + [10]).each do |a|
50
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a} on second find"
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,39 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'mongo'
3
+ require 'test/unit'
4
+ require 'test/test_helper'
5
+
6
+ # NOTE: this test should be run only if a replica pair is running.
7
+ class ReplicaPairQueryTest < Test::Unit::TestCase
8
+ include Mongo
9
+
10
+ def setup
11
+ @conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil)
12
+ @db = @conn.db('mongo-ruby-test')
13
+ @db.drop_collection("test-pairs")
14
+ @coll = @db.collection("test-pairs")
15
+ end
16
+
17
+ def test_query
18
+ @coll.save({:a => 20})
19
+ @coll.save({:a => 30})
20
+ @coll.save({:a => 40})
21
+ results = []
22
+ @coll.find.each {|r| results << r}
23
+ [20, 30, 40].each do |a|
24
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
25
+ end
26
+
27
+ puts "Please disconnect the current master."
28
+ gets
29
+
30
+ results = []
31
+ rescue_connection_failure do
32
+ @coll.find.each {|r| results << r}
33
+ [20, 30, 40].each do |a|
34
+ assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"
35
+ end
36
+ end
37
+ end
38
+
39
+ end
@@ -144,7 +144,7 @@ class TestCollection < Test::Unit::TestCase
144
144
 
145
145
  # Can't duplicate an index.
146
146
  assert_raise OperationFailure do
147
- @@test.update({}, {"x" => 10}, :safe => true, :upsert => true)
147
+ @@test.update({}, {"x" => 10}, :safe => true)
148
148
  end
149
149
  end
150
150
  end
@@ -154,7 +154,6 @@ class TestCollection < Test::Unit::TestCase
154
154
 
155
155
  @@test.save("hello" => "world")
156
156
  @@test.save("hello" => "world")
157
- assert(@@db.error.include?("E11000"))
158
157
 
159
158
  assert_raise OperationFailure do
160
159
  @@test.save({"hello" => "world"}, :safe => true)
@@ -266,6 +265,28 @@ class TestCollection < Test::Unit::TestCase
266
265
  assert c.closed?
267
266
  end
268
267
 
268
+ def test_mapreduce
269
+ @@test << { "user_id" => 1 }
270
+ @@test << { "user_id" => 2 }
271
+
272
+ m = "function() { emit(this.user_id, 1); }"
273
+ r = "function(k,vals) { return 1; }"
274
+ res = @@test.map_reduce(m, r);
275
+ assert res.find_one({"_id" => 1})
276
+ assert res.find_one({"_id" => 2})
277
+ end
278
+
279
+ def test_mapreduce_with_code_objects
280
+ @@test << { "user_id" => 1 }
281
+ @@test << { "user_id" => 2 }
282
+
283
+ m = Code.new("function() { emit(this.user_id, 1); }")
284
+ r = Code.new("function(k,vals) { return 1; }")
285
+ res = @@test.map_reduce(m, r);
286
+ assert res.find_one({"_id" => 1})
287
+ assert res.find_one({"_id" => 2})
288
+ end
289
+
269
290
  def test_saving_dates_pre_epoch
270
291
  begin
271
292
  @@test.save({'date' => Time.utc(1600)})
@@ -291,9 +312,6 @@ class TestCollection < Test::Unit::TestCase
291
312
  @@test.save(:foo => i)
292
313
  end
293
314
 
294
- # TODO remove test for deprecated :offset option
295
- assert_equal 5, @@test.find({}, :offset => 5).next_object()["foo"]
296
-
297
315
  assert_equal 5, @@test.find({}, :skip => 5).next_object()["foo"]
298
316
  assert_equal nil, @@test.find({}, :skip => 10).next_object()
299
317
 
@@ -388,11 +406,6 @@ class TestCollection < Test::Unit::TestCase
388
406
  assert_equal 0, @collection.find.count
389
407
  end
390
408
 
391
- should "remove all records if deprecated clear is used" do
392
- @collection.clear
393
- assert_equal 0, @collection.find.count
394
- end
395
-
396
409
  should "remove only matching records" do
397
410
  @collection.remove({:name => "Jones"})
398
411
  assert_equal 1, @collection.size
@@ -79,8 +79,7 @@ class TestConnection < Test::Unit::TestCase
79
79
  logger = Logger.new(output)
80
80
  logger.level = Logger::DEBUG
81
81
  db = Connection.new(@host, @port, :logger => logger).db('ruby-mongo-test')
82
-
83
- assert output.string.include?("$cmd.find")
82
+ assert output.string.include?("admin.$cmd.find")
84
83
  end
85
84
 
86
85
  def test_connection_logger
@@ -106,23 +105,23 @@ class TestConnection < Test::Unit::TestCase
106
105
  assert !@mongo.database_names.include?('ruby-mongo-will-be-deleted')
107
106
  end
108
107
 
109
- def test_pair
110
- db = Connection.new({:left => ['foo', 123]})
111
- pair = db.instance_variable_get('@pair')
112
- assert_equal 2, pair.length
113
- assert_equal ['foo', 123], pair[0]
114
- assert_equal ['localhost', Connection::DEFAULT_PORT], pair[1]
115
-
116
- db = Connection.new({:right => 'bar'})
117
- pair = db.instance_variable_get('@pair')
118
- assert_equal 2, pair.length
119
- assert_equal ['localhost', Connection::DEFAULT_PORT], pair[0]
120
- assert_equal ['bar', Connection::DEFAULT_PORT], pair[1]
121
-
122
- db = Connection.new({:right => ['foo', 123], :left => 'bar'})
123
- pair = db.instance_variable_get('@pair')
124
- assert_equal 2, pair.length
125
- assert_equal ['bar', Connection::DEFAULT_PORT], pair[0]
126
- assert_equal ['foo', 123], pair[1]
108
+ def test_nodes
109
+ db = Connection.new({:left => ['foo', 123]}, nil, :connect => false)
110
+ nodes = db.nodes
111
+ assert_equal 2, db.nodes.length
112
+ assert_equal ['foo', 123], nodes[0]
113
+ assert_equal ['localhost', Connection::DEFAULT_PORT], nodes[1]
114
+
115
+ db = Connection.new({:right => 'bar'}, nil, :connect => false)
116
+ nodes = db.nodes
117
+ assert_equal 2, nodes.length
118
+ assert_equal ['localhost', Connection::DEFAULT_PORT], nodes[0]
119
+ assert_equal ['bar', Connection::DEFAULT_PORT], nodes[1]
120
+
121
+ db = Connection.new({:right => ['foo', 123], :left => 'bar'}, nil, :connect => false)
122
+ nodes = db.nodes
123
+ assert_equal 2, nodes.length
124
+ assert_equal ['bar', Connection::DEFAULT_PORT], nodes[0]
125
+ assert_equal ['foo', 123], nodes[1]
127
126
  end
128
127
  end
@@ -28,7 +28,7 @@ class ConversionsTest < Test::Unit::TestCase
28
28
  end
29
29
 
30
30
  def test_symbol_as_sort_parameters
31
- params = symbol_as_sort_parameters(:field)
31
+ params = string_as_sort_parameters(:field)
32
32
  assert_equal({ "field" => 1 }, params)
33
33
  end
34
34
 
@@ -118,4 +118,4 @@ class ConversionsTest < Test::Unit::TestCase
118
118
  end
119
119
  end
120
120
 
121
- end
121
+ end
@@ -246,26 +246,26 @@ class CursorTest < Test::Unit::TestCase
246
246
  def test_kill_cursors
247
247
  @@coll.drop
248
248
 
249
- client_cursors = @@db.db_command("cursorInfo" => 1)["clientCursors_size"]
250
- by_location = @@db.db_command("cursorInfo" => 1)["byLocation_size"]
249
+ client_cursors = @@db.command("cursorInfo" => 1)["clientCursors_size"]
250
+ by_location = @@db.command("cursorInfo" => 1)["byLocation_size"]
251
251
 
252
252
  10000.times do |i|
253
253
  @@coll.insert("i" => i)
254
254
  end
255
255
 
256
256
  assert_equal(client_cursors,
257
- @@db.db_command("cursorInfo" => 1)["clientCursors_size"])
257
+ @@db.command("cursorInfo" => 1)["clientCursors_size"])
258
258
  assert_equal(by_location,
259
- @@db.db_command("cursorInfo" => 1)["byLocation_size"])
259
+ @@db.command("cursorInfo" => 1)["byLocation_size"])
260
260
 
261
261
  10.times do |i|
262
262
  @@coll.find_one()
263
263
  end
264
264
 
265
265
  assert_equal(client_cursors,
266
- @@db.db_command("cursorInfo" => 1)["clientCursors_size"])
266
+ @@db.command("cursorInfo" => 1)["clientCursors_size"])
267
267
  assert_equal(by_location,
268
- @@db.db_command("cursorInfo" => 1)["byLocation_size"])
268
+ @@db.command("cursorInfo" => 1)["byLocation_size"])
269
269
 
270
270
  10.times do |i|
271
271
  a = @@coll.find()
@@ -274,49 +274,49 @@ class CursorTest < Test::Unit::TestCase
274
274
  end
275
275
 
276
276
  assert_equal(client_cursors,
277
- @@db.db_command("cursorInfo" => 1)["clientCursors_size"])
277
+ @@db.command("cursorInfo" => 1)["clientCursors_size"])
278
278
  assert_equal(by_location,
279
- @@db.db_command("cursorInfo" => 1)["byLocation_size"])
279
+ @@db.command("cursorInfo" => 1)["byLocation_size"])
280
280
 
281
281
  a = @@coll.find()
282
282
  a.next_object()
283
283
 
284
284
  assert_not_equal(client_cursors,
285
- @@db.db_command("cursorInfo" => 1)["clientCursors_size"])
285
+ @@db.command("cursorInfo" => 1)["clientCursors_size"])
286
286
  assert_not_equal(by_location,
287
- @@db.db_command("cursorInfo" => 1)["byLocation_size"])
287
+ @@db.command("cursorInfo" => 1)["byLocation_size"])
288
288
 
289
289
  a.close()
290
290
 
291
291
  assert_equal(client_cursors,
292
- @@db.db_command("cursorInfo" => 1)["clientCursors_size"])
292
+ @@db.command("cursorInfo" => 1)["clientCursors_size"])
293
293
  assert_equal(by_location,
294
- @@db.db_command("cursorInfo" => 1)["byLocation_size"])
294
+ @@db.command("cursorInfo" => 1)["byLocation_size"])
295
295
 
296
296
  a = @@coll.find({}, :limit => 10).next_object()
297
297
 
298
298
  assert_equal(client_cursors,
299
- @@db.db_command("cursorInfo" => 1)["clientCursors_size"])
299
+ @@db.command("cursorInfo" => 1)["clientCursors_size"])
300
300
  assert_equal(by_location,
301
- @@db.db_command("cursorInfo" => 1)["byLocation_size"])
301
+ @@db.command("cursorInfo" => 1)["byLocation_size"])
302
302
 
303
303
  @@coll.find() do |cursor|
304
304
  cursor.next_object()
305
305
  end
306
306
 
307
307
  assert_equal(client_cursors,
308
- @@db.db_command("cursorInfo" => 1)["clientCursors_size"])
308
+ @@db.command("cursorInfo" => 1)["clientCursors_size"])
309
309
  assert_equal(by_location,
310
- @@db.db_command("cursorInfo" => 1)["byLocation_size"])
310
+ @@db.command("cursorInfo" => 1)["byLocation_size"])
311
311
 
312
312
  @@coll.find() { |cursor|
313
313
  cursor.next_object()
314
314
  }
315
315
 
316
316
  assert_equal(client_cursors,
317
- @@db.db_command("cursorInfo" => 1)["clientCursors_size"])
317
+ @@db.command("cursorInfo" => 1)["clientCursors_size"])
318
318
  assert_equal(by_location,
319
- @@db.db_command("cursorInfo" => 1)["byLocation_size"])
319
+ @@db.command("cursorInfo" => 1)["byLocation_size"])
320
320
  end
321
321
 
322
322
  def test_count_with_fields