mongo 0.20.1 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -35,7 +35,6 @@ The driver also requires the BSON gem:
35
35
  $ gem install bson
36
36
 
37
37
  And for a significant performance boost, you'll want to install the C extensions:
38
- extensions:
39
38
 
40
39
  $ gem install bson_ext
41
40
 
@@ -9,13 +9,14 @@ host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
9
9
  port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
10
10
 
11
11
  puts "Connecting to #{host}:#{port}"
12
- db = Mongo::Connection.new(host, port).db('ruby-mongo-examples')
12
+ con = Mongo::Connection.new(host, port)
13
+ db = con.db('ruby-mongo-examples')
13
14
  coll = db.create_collection('test')
14
15
 
15
16
  # Erase all records from collection, if any
16
17
  coll.remove
17
18
 
18
- admin = db.admin
19
+ admin = con['admin']
19
20
 
20
21
  # Profiling level set/get
21
22
  puts "Profiling level: #{admin.profiling_level}"
@@ -34,7 +35,7 @@ pp admin.profiling_info
34
35
 
35
36
  # Validate returns a hash if all is well and
36
37
  # raises an exception if there is a problem.
37
- info = admin.validate_collection(coll.name)
38
+ info = db.validate_collection(coll.name)
38
39
  puts "valid = #{info['ok']}"
39
40
  puts info['result']
40
41
 
@@ -24,7 +24,7 @@ p db.collection_names
24
24
  p db.collections_info
25
25
 
26
26
  # Index information
27
- db.create_index('test', 'a')
27
+ coll.create_index('a')
28
28
  p db.index_information('test')
29
29
 
30
30
  # Destroy the collection
@@ -1,7 +1,7 @@
1
1
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
 
3
3
  module Mongo
4
- VERSION = "0.20.1"
4
+ VERSION = "1.0"
5
5
  end
6
6
 
7
7
  module Mongo
@@ -19,8 +19,11 @@ module Mongo
19
19
  OP_DELETE = 2006
20
20
  OP_KILL_CURSORS = 2007
21
21
 
22
+ OP_QUERY_TAILABLE = 2
22
23
  OP_QUERY_SLAVE_OK = 4
23
24
  OP_QUERY_NO_CURSOR_TIMEOUT = 16
25
+
26
+ DEFAULT_BATCH_SIZE = 100
24
27
  end
25
28
 
26
29
  end
@@ -120,6 +120,8 @@ module Mongo
120
120
  # @option opts [Boolean] :snapshot ('false') if true, snapshot mode will be used for this query.
121
121
  # Snapshot mode assures no duplicates are returned, or objects missed, which were preset at both the start and
122
122
  # end of the query's execution. For details see http://www.mongodb.org/display/DOCS/How+to+do+Snapshotting+in+the+Mongo+Database
123
+ # @option opts [Boolean] :batch_size (100) the number of documents to returned by the database per GETMORE operation. A value of 0
124
+ # will let the database server decide how many results to returns. This option can be ignored for most use cases.
123
125
  # @option opts [Boolean] :timeout ('true') when +true+, the returned cursor will be subject to
124
126
  # the normal cursor timeout behavior of the mongod process. When +false+, the returned cursor will never timeout. Note
125
127
  # that disabling timeout will only work when #find is invoked with a block. This is to prevent any inadvertant failure to
@@ -140,6 +142,7 @@ module Mongo
140
142
  sort = opts.delete(:sort)
141
143
  hint = opts.delete(:hint)
142
144
  snapshot = opts.delete(:snapshot)
145
+ batch_size = opts.delete(:batch_size)
143
146
  if opts[:timeout] == false && !block_given?
144
147
  raise ArgumentError, "Timeout can be set to false only when #find is invoked with a block."
145
148
  end
@@ -152,7 +155,7 @@ module Mongo
152
155
  raise RuntimeError, "Unknown options [#{opts.inspect}]" unless opts.empty?
153
156
 
154
157
  cursor = Cursor.new(self, :selector => selector, :fields => fields, :skip => skip, :limit => limit,
155
- :order => sort, :hint => hint, :snapshot => snapshot, :timeout => timeout)
158
+ :order => sort, :hint => hint, :snapshot => snapshot, :timeout => timeout, :batch_size => batch_size)
156
159
  if block_given?
157
160
  yield cursor
158
161
  cursor.close()
@@ -330,9 +333,6 @@ module Mongo
330
333
  # Also note that it is permissible to create compound indexes that include a geospatial index as
331
334
  # long as the geospatial index comes first.
332
335
  #
333
- # @param [Boolean] unique if true, this index will enforce a uniqueness constraint. DEPRECATED. Future
334
- # versions of this driver will specify the uniqueness constraint using a hash param.
335
- #
336
336
  # @option opts [Boolean] :unique (false) if true, this index will enforce a uniqueness constraint.
337
337
  # @option opts [Boolean] :background (false) indicate that the index should be built in the background. This
338
338
  # feature is only available in MongoDB >= 1.3.2.
@@ -359,32 +359,36 @@ module Mongo
359
359
  #
360
360
  # @core indexes create_index-instance_method
361
361
  def create_index(spec, opts={})
362
- opts.assert_valid_keys(:min, :max, :background, :unique, :dropDups) if opts.is_a?(Hash)
362
+ opts.assert_valid_keys(:min, :max, :background, :unique, :dropDups)
363
363
  field_spec = OrderedHash.new
364
364
  if spec.is_a?(String) || spec.is_a?(Symbol)
365
365
  field_spec[spec.to_s] = 1
366
366
  elsif spec.is_a?(Array) && spec.all? {|field| field.is_a?(Array) }
367
- spec.each { |f| field_spec[f[0].to_s] = f[1] }
367
+ spec.each do |f|
368
+ if [Mongo::ASCENDING, Mongo::DESCENDING, Mongo::GEO2D].include?(f[1])
369
+ field_spec[f[0].to_s] = f[1]
370
+ else
371
+ raise MongoArgumentError, "Invalid index field #{f[1].inspect}; " +
372
+ "should be one of Mongo::ASCENDING (1), Mongo::DESCENDING (-1) or Mongo::GEO2D ('2d')."
373
+ end
374
+ end
368
375
  else
369
376
  raise MongoArgumentError, "Invalid index specification #{spec.inspect}; " +
370
377
  "should be either a string, symbol, or an array of arrays."
371
378
  end
372
379
 
373
380
  name = generate_index_name(field_spec)
374
- if opts == true || opts == false
375
- warn "For Collection#create_index, the method for specifying a unique index has changed." +
376
- "Please pass :unique => true to the method instead."
377
- end
378
- sel = {
381
+
382
+ selector = {
379
383
  :name => name,
380
384
  :ns => "#{@db.name}.#{@name}",
381
- :key => field_spec,
382
- :unique => (opts == true ? true : false) }
383
- sel.merge!(opts) if opts.is_a?(Hash)
385
+ :key => field_spec
386
+ }
387
+ selector.merge!(opts)
384
388
  begin
385
- response = insert_documents([sel], Mongo::DB::SYSTEM_INDEX_COLLECTION, false, true)
389
+ response = insert_documents([selector], Mongo::DB::SYSTEM_INDEX_COLLECTION, false, true)
386
390
  rescue Mongo::OperationFailure
387
- raise Mongo::OperationFailure, "Failed to create index #{sel.inspect} with the following errors: #{response}"
391
+ raise Mongo::OperationFailure, "Failed to create index #{selector.inspect} with the following errors: #{response}"
388
392
  end
389
393
  name
390
394
  end
@@ -118,11 +118,11 @@ module Mongo
118
118
  # @param opts Takes the same options as Connection.new
119
119
  #
120
120
  # @example
121
- # Connection.new([["db1.example.com", 27017],
121
+ # Connection.paired([["db1.example.com", 27017],
122
122
  # ["db2.example.com", 27017]])
123
123
  #
124
124
  # @example
125
- # Connection.new([["db1.example.com", 27017],
125
+ # Connection.paired([["db1.example.com", 27017],
126
126
  # ["db2.example.com", 27017]],
127
127
  # :pool_size => 20, :timeout => 5)
128
128
  #
@@ -47,6 +47,8 @@ module Mongo
47
47
  @timeout = options[:timeout] || false
48
48
  @explain = options[:explain]
49
49
  @socket = options[:socket]
50
+ @tailable = options[:tailable] || false
51
+ @batch_size = options[:batch_size] || Mongo::Constants::DEFAULT_BATCH_SIZE
50
52
 
51
53
  @full_collection_name = "#{@collection.db.name}.#{@collection.name}"
52
54
  @cache = []
@@ -250,7 +252,8 @@ module Mongo
250
252
  def query_opts
251
253
  timeout = @timeout ? 0 : Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT
252
254
  slave_ok = @connection.slave_ok? ? Mongo::Constants::OP_QUERY_SLAVE_OK : 0
253
- slave_ok + timeout
255
+ tailable = @tailable ? Mongo::Constants::OP_QUERY_TAILABLE : 0
256
+ slave_ok + timeout + tailable
254
257
  end
255
258
 
256
259
  # Get the query options for this Cursor.
@@ -317,8 +320,8 @@ module Mongo
317
320
  db_name = @admin ? 'admin' : @db.name
318
321
  BSON::BSON_RUBY.serialize_cstr(message, "#{db_name}.#{@collection.name}")
319
322
 
320
- # Number of results to return; db decides for now.
321
- message.put_int(100)
323
+ # Number of results to return.
324
+ message.put_int(@batch_size)
322
325
 
323
326
  # Cursor id.
324
327
  message.put_long(@cursor_id)
@@ -404,8 +404,11 @@ module Mongo
404
404
  # @param [Boolean] unique if +true+, the created index will enforce a uniqueness constraint.
405
405
  #
406
406
  # @return [String] the name of the index created.
407
+ #
408
+ # @deprecated
407
409
  def create_index(collection_name, field_or_spec, unique=false)
408
- self.collection(collection_name).create_index(field_or_spec, unique)
410
+ warn "DB#create_index is now deprecated. Please use Collection#create_index instead."
411
+ self.collection(collection_name).create_index(field_or_spec, :unique => unique)
409
412
  end
410
413
 
411
414
  # Return +true+ if the supplied +doc+ contains an 'ok' field with the value 1.
@@ -39,6 +39,9 @@ module Mongo
39
39
 
40
40
  # Store a file in the file store.
41
41
  #
42
+ # Note that arbitary metadata attributes can be saved to the file by passing
43
+ # them is as options.
44
+ #
42
45
  # @param [String, #read] data a string or io-like object to store.
43
46
  #
44
47
  # @options opts [String] :filename (nil) a name for the file.
@@ -53,14 +56,8 @@ module Mongo
53
56
  # will be validated using an md5 hash. If validation fails, an exception will be raised.
54
57
  #
55
58
  # @return [Mongo::ObjectID] the file's id.
56
- def put(data, opts={}, old_opts={})
57
- if opts.is_a?(String)
58
- warn "The filename is now optional. Please pass the filename as a hash option: Grid#put(data, :filename => 'file.jpg')."
59
- filename = opts
60
- opts = old_opts
61
- else
62
- filename = opts[:filename]
63
- end
59
+ def put(data, opts={})
60
+ filename = opts[:filename]
64
61
  opts.merge!(default_grid_io_opts)
65
62
  file = GridIO.new(@files, @chunks, filename, 'w', opts=opts)
66
63
  file.write(data)
@@ -0,0 +1,30 @@
1
+ # --
2
+ # Copyright (C) 2008-2010 10gen Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ++
16
+
17
+ module Mongo
18
+ module ClassMethods
19
+
20
+ def exists?(criteria)
21
+ BSON::ObjectID:
22
+ @files.find_one(query)
23
+ end
24
+
25
+ def list(query={})
26
+ @files.find(query)
27
+ end
28
+
29
+ end
30
+ end
@@ -43,6 +43,9 @@ module Mongo
43
43
  # Open a file for reading or writing. Note that the options for this method only apply
44
44
  # when opening in 'w' mode.
45
45
  #
46
+ # Note that arbitary metadata attributes can be saved to the file by passing
47
+ # them is as options.
48
+ #
46
49
  # @param [String] filename the name of the file.
47
50
  # @param [String] mode either 'r' or 'w' for reading from
48
51
  # or writing to the file.
@@ -105,7 +108,7 @@ module Mongo
105
108
  # Delete the file with the given filename. Note that this will delete
106
109
  # all versions of the file.
107
110
  #
108
- # Note that deleting a GridFS file can result in read errors if another process
111
+ # Be careful with this. Deleting a GridFS file can result in read errors if another process
109
112
  # is attempting to read a file while it's being deleted. While the odds for this
110
113
  # kind of race condition are small, it's important to be aware of.
111
114
  #
@@ -165,7 +165,7 @@ class TestCollection < Test::Unit::TestCase
165
165
  end
166
166
  else
167
167
  def test_safe_update
168
- @@test.create_index("x", true)
168
+ @@test.create_index("x", :unique => true)
169
169
  @@test.insert("x" => 5)
170
170
  @@test.insert("x" => 10)
171
171
 
@@ -182,7 +182,7 @@ class TestCollection < Test::Unit::TestCase
182
182
  end
183
183
 
184
184
  def test_safe_save
185
- @@test.create_index("hello", true)
185
+ @@test.create_index("hello", :unique => true)
186
186
 
187
187
  @@test.save("hello" => "world")
188
188
  @@test.save("hello" => "world")
@@ -558,7 +558,7 @@ class TestCollection < Test::Unit::TestCase
558
558
  end
559
559
 
560
560
  should "create a unique index" do
561
- @collection.create_index([['a', Mongo::ASCENDING]], true)
561
+ @collection.create_index([['a', Mongo::ASCENDING]], :unique => true)
562
562
  assert @collection.index_information['a_1']['unique'] == true
563
563
  end
564
564
 
@@ -577,6 +577,12 @@ class TestCollection < Test::Unit::TestCase
577
577
  end
578
578
  end
579
579
 
580
+ should "enforce proper index types" do
581
+ assert_raise MongoArgumentError do
582
+ @collection.create_index([['c', 'blah']])
583
+ end
584
+ end
585
+
580
586
  should "generate indexes in the proper order" do
581
587
  @collection.expects(:insert_documents) do |sel, coll, safe|
582
588
  assert_equal 'b_1_a_1', sel[:name]
@@ -594,4 +600,42 @@ class TestCollection < Test::Unit::TestCase
594
600
  end
595
601
  end
596
602
  end
603
+
604
+ context "Capped collections" do
605
+ setup do
606
+ @@db.drop_collection('log')
607
+ @capped = @@db.create_collection('log', :capped => true, :size => 1024)
608
+
609
+ 10.times { |n| @capped.insert({:n => n}) }
610
+ end
611
+
612
+ should "find using a standard cursor" do
613
+ cursor = @capped.find
614
+ 10.times do
615
+ assert cursor.next_document
616
+ end
617
+ assert_nil cursor.next_document
618
+ @capped.insert({:n => 100})
619
+ assert_nil cursor.next_document
620
+ end
621
+
622
+ should "" do
623
+ col = @@db['regular-collection']
624
+ col.insert({:a => 1000})
625
+ tail = Cursor.new(col, :tailable => true, :order => [['$natural', 1]])
626
+ assert_raise OperationFailure do
627
+ tail.next_document
628
+ end
629
+ end
630
+
631
+ should "find using a tailable cursor" do
632
+ tail = Cursor.new(@capped, :tailable => true, :order => [['$natural', 1]])
633
+ 10.times do
634
+ assert tail.next_document
635
+ end
636
+ assert_nil tail.next_document
637
+ @capped.insert({:n => 100})
638
+ assert tail.next_document
639
+ end
640
+ end
597
641
  end
@@ -275,7 +275,7 @@ class DBAPITest < Test::Unit::TestCase
275
275
  def test_index_information
276
276
  assert_equal @@coll.index_information.length, 1
277
277
 
278
- name = @@db.create_index(@@coll.name, 'a')
278
+ name = @@coll.create_index('a')
279
279
  info = @@db.index_information(@@coll.name)
280
280
  assert_equal name, "a_1"
281
281
  assert_equal @@coll.index_information, info
@@ -303,7 +303,7 @@ class DBAPITest < Test::Unit::TestCase
303
303
  end
304
304
 
305
305
  def test_multiple_index_cols
306
- name = @@db.create_index(@@coll.name, [['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]])
306
+ name = @@coll.create_index([['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]])
307
307
  info = @@db.index_information(@@coll.name)
308
308
  assert_equal 2, info.length
309
309
 
@@ -315,7 +315,7 @@ class DBAPITest < Test::Unit::TestCase
315
315
  end
316
316
 
317
317
  def test_multiple_index_cols_with_symbols
318
- name = @@db.create_index(@@coll.name, [[:a, DESCENDING], [:b, ASCENDING], [:c, DESCENDING]])
318
+ name = @@coll.create_index([[:a, DESCENDING], [:b, ASCENDING], [:c, DESCENDING]])
319
319
  info = @@db.index_information(@@coll.name)
320
320
  assert_equal 2, info.length
321
321
 
@@ -338,7 +338,7 @@ class DBAPITest < Test::Unit::TestCase
338
338
 
339
339
  @@db.drop_collection("blah")
340
340
  test = @@db.collection("blah")
341
- test.create_index("hello", unique=true)
341
+ test.create_index("hello", :unique => true)
342
342
 
343
343
  test.insert("hello" => "world")
344
344
  test.insert("hello" => "mike")
@@ -357,7 +357,7 @@ class DBAPITest < Test::Unit::TestCase
357
357
 
358
358
  @@db.drop_collection("blah")
359
359
  test = @@db.collection("blah")
360
- test.create_index("hello.a", unique=true)
360
+ test.create_index("hello.a", :unique => true)
361
361
 
362
362
  test.insert("hello" => {"a" => 4, "b" => 5})
363
363
  test.insert("hello" => {"a" => 7, "b" => 2})
@@ -19,7 +19,7 @@ class GridTest < Test::Unit::TestCase
19
19
  setup do
20
20
  @data = "GRIDDATA" * 50000
21
21
  @grid = Grid.new(@db, 'test-fs')
22
- @id = @grid.put(@data, 'sample', :metadata => {'app' => 'photos'})
22
+ @id = @grid.put(@data, :filename => 'sample', :metadata => {'app' => 'photos'})
23
23
  end
24
24
 
25
25
  should "retrieve the stored data" do
@@ -58,7 +58,7 @@ class GridTest < Test::Unit::TestCase
58
58
  end
59
59
 
60
60
  should "store the file with the old filename api" do
61
- id = @grid.put(@data, 'sample', :metadata => @metadata)
61
+ id = @grid.put(@data, :filename => 'sample', :metadata => @metadata)
62
62
  file = @grid.get(id)
63
63
  assert_equal 'sample', file.filename
64
64
  assert_equal @metadata, file.metadata
@@ -106,7 +106,7 @@ class GridTest < Test::Unit::TestCase
106
106
  context "Storing data with a length of zero" do
107
107
  setup do
108
108
  @grid = Grid.new(@db, 'test-fs')
109
- @id = @grid.put('', 'sample', :metadata => {'app' => 'photos'})
109
+ @id = @grid.put('', :filename => 'sample', :metadata => {'app' => 'photos'})
110
110
  end
111
111
 
112
112
  should "return the zero length" do
@@ -119,7 +119,7 @@ class GridTest < Test::Unit::TestCase
119
119
  setup do
120
120
  def read_and_write_stream(filename, read_length, opts={})
121
121
  io = File.open(File.join(File.dirname(__FILE__), 'data', filename), 'r')
122
- id = @grid.put(io, filename + read_length.to_s, opts)
122
+ id = @grid.put(io, opts.merge!(:filename => filename + read_length.to_s))
123
123
  file = @grid.get(id)
124
124
  io.rewind
125
125
  data = io.read
@@ -19,7 +19,7 @@ class TestThreadingLargePool < Test::Unit::TestCase
19
19
  @duplicate.insert("test" => "update")
20
20
  @unique.insert("test" => "insert")
21
21
  @unique.insert("test" => "update")
22
- @unique.create_index("test", true)
22
+ @unique.create_index("test", :unique => true)
23
23
  end
24
24
 
25
25
  def test_safe_update
@@ -17,7 +17,7 @@ class TestThreading < Test::Unit::TestCase
17
17
  @duplicate.insert("test" => "update")
18
18
  @unique.insert("test" => "insert")
19
19
  @unique.insert("test" => "update")
20
- @unique.create_index("test", true)
20
+ @unique.create_index("test", :unique => true)
21
21
  end
22
22
 
23
23
  def test_safe_update
metadata CHANGED
@@ -3,10 +3,9 @@ name: mongo
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
- - 0
7
- - 20
8
6
  - 1
9
- version: 0.20.1
7
+ - 0
8
+ version: "1.0"
10
9
  platform: ruby
11
10
  authors:
12
11
  - Jim Menard
@@ -16,7 +15,7 @@ autorequire:
16
15
  bindir: bin
17
16
  cert_chain: []
18
17
 
19
- date: 2010-04-07 00:00:00 -04:00
18
+ date: 2010-04-29 00:00:00 -04:00
20
19
  default_executable:
21
20
  dependencies:
22
21
  - !ruby/object:Gem::Dependency
@@ -27,10 +26,9 @@ dependencies:
27
26
  - - "="
28
27
  - !ruby/object:Gem::Version
29
28
  segments:
30
- - 0
31
- - 20
32
29
  - 1
33
- version: 0.20.1
30
+ - 0
31
+ version: "1.0"
34
32
  type: :runtime
35
33
  version_requirements: *id001
36
34
  description: A Ruby driver for MongoDB. For more information about Mongo, see http://www.mongodb.org.
@@ -53,6 +51,7 @@ files:
53
51
  - lib/mongo/db.rb
54
52
  - lib/mongo/exceptions.rb
55
53
  - lib/mongo/gridfs/grid.rb
54
+ - lib/mongo/gridfs/grid_ext.rb
56
55
  - lib/mongo/gridfs/grid_file_system.rb
57
56
  - lib/mongo/gridfs/grid_io.rb
58
57
  - lib/mongo/util/conversions.rb