mongo 0.18.2 → 0.18.3

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 (51) hide show
  1. data/README.rdoc +37 -28
  2. data/Rakefile +19 -0
  3. data/bin/objectid_benchmark.rb +23 -0
  4. data/examples/admin.rb +7 -6
  5. data/examples/capped.rb +3 -4
  6. data/examples/cursor.rb +4 -3
  7. data/examples/gridfs.rb +3 -2
  8. data/examples/index_test.rb +10 -9
  9. data/examples/info.rb +3 -2
  10. data/examples/queries.rb +3 -2
  11. data/examples/simple.rb +3 -2
  12. data/examples/strict.rb +2 -1
  13. data/examples/types.rb +4 -3
  14. data/lib/mongo.rb +29 -12
  15. data/lib/mongo/admin.rb +17 -2
  16. data/lib/mongo/collection.rb +230 -169
  17. data/lib/mongo/connection.rb +136 -91
  18. data/lib/mongo/cursor.rb +68 -40
  19. data/lib/mongo/db.rb +247 -123
  20. data/lib/mongo/{errors.rb → exceptions.rb} +6 -5
  21. data/lib/mongo/gridfs.rb +6 -0
  22. data/lib/mongo/gridfs/grid_store.rb +142 -94
  23. data/lib/mongo/types/binary.rb +11 -1
  24. data/lib/mongo/types/code.rb +6 -1
  25. data/lib/mongo/types/dbref.rb +7 -2
  26. data/lib/mongo/types/min_max_keys.rb +58 -0
  27. data/lib/mongo/types/objectid.rb +76 -20
  28. data/lib/mongo/types/regexp_of_holding.rb +5 -0
  29. data/lib/mongo/util/bson_ruby.rb +36 -2
  30. data/lib/mongo/util/byte_buffer.rb +18 -2
  31. data/lib/mongo/util/conversions.rb +6 -5
  32. data/lib/mongo/util/ordered_hash.rb +3 -1
  33. data/lib/mongo/util/support.rb +3 -0
  34. data/lib/mongo/util/xml_to_ruby.rb +7 -0
  35. data/test/test_bson.rb +48 -0
  36. data/test/test_collection.rb +13 -0
  37. data/test/test_connection.rb +35 -0
  38. data/test/test_conversions.rb +1 -1
  39. data/test/test_cursor.rb +37 -5
  40. data/test/test_db.rb +51 -2
  41. data/test/test_db_api.rb +4 -7
  42. data/test/test_grid_store.rb +10 -0
  43. data/test/test_objectid.rb +16 -2
  44. data/test/test_ordered_hash.rb +14 -0
  45. data/test/threading/test_threading_large_pool.rb +4 -4
  46. data/test/unit/db_test.rb +43 -0
  47. metadata +5 -7
  48. data/examples/benchmarks.rb +0 -42
  49. data/examples/blog.rb +0 -76
  50. data/lib/mongo/constants.rb +0 -15
  51. data/test/mongo-qa/_common.rb +0 -8
@@ -1,18 +1,18 @@
1
- # Copyright 2009 10gen, Inc.
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
2
3
  #
3
4
  # Licensed under the Apache License, Version 2.0 (the "License");
4
5
  # you may not use this file except in compliance with the License.
5
6
  # You may obtain a copy of the License at
6
7
  #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
+ # http://www.apache.org/licenses/LICENSE-2.0
8
9
  #
9
10
  # Unless required by applicable law or agreed to in writing, software
10
11
  # distributed under the License is distributed on an "AS IS" BASIS,
11
12
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
13
  # See the License for the specific language governing permissions and
13
14
  # limitations under the License.
14
-
15
- # Exceptions raised by the MongoDB driver.
15
+ # ++
16
16
 
17
17
  module Mongo
18
18
  # Generic Mongo Ruby Driver exception class.
@@ -39,7 +39,8 @@ module Mongo
39
39
  # Raised on failures in connection to the database server.
40
40
  class ConnectionTimeoutError < MongoRubyError; end
41
41
 
42
- # Raised when trying to insert a document that exceeds the 4MB limit.
42
+ # Raised when trying to insert a document that exceeds the 4MB limit or
43
+ # when the document contains objects that can't be serialized as BSON.
43
44
  class InvalidDocument < MongoDBError; end
44
45
 
45
46
  # Raised when a database operation fails.
@@ -14,3 +14,9 @@
14
14
  # limitations under the License.
15
15
  # ++
16
16
  require 'mongo/gridfs/grid_store'
17
+
18
+ # GridFS is a specification for storing large binary objects in MongoDB.
19
+ # See the documentation for GridFS::GridStore
20
+ # @see GridFS::GridStore
21
+ module GridFS
22
+ end
@@ -20,25 +20,32 @@ require 'mongo/gridfs/chunk'
20
20
 
21
21
  module GridFS
22
22
 
23
- # GridStore is an IO-like object that provides input and output for
24
- # streams of data to Mongo. See Mongo's documentation about GridFS for
25
- # storage implementation details.
23
+ # GridStore is an IO-like class that provides input and output for
24
+ # streams of data to MongoDB.
26
25
  #
27
- # Example code:
26
+ # @example
28
27
  #
29
- # require 'mongo/gridfs'
30
- # GridStore.open(database, 'filename', 'w') { |f|
31
- # f.puts "Hello, world!"
32
- # }
33
- # GridStore.open(database, 'filename, 'r') { |f|
34
- # puts f.read # => Hello, world!\n
35
- # }
36
- # GridStore.open(database, 'filename', 'w+') { |f|
37
- # f.puts "But wait, there's more!"
38
- # }
39
- # GridStore.open(database, 'filename, 'r') { |f|
40
- # puts f.read # => Hello, world!\nBut wait, there's more!\n
41
- # }
28
+ # include GridFS
29
+ #
30
+ # #Store the text "Hello, world!" in the grid store.
31
+ # GridStore.open(database, 'filename', 'w') do |f|
32
+ # f.puts "Hello, world!"
33
+ # end
34
+ #
35
+ # # Output "Hello, world!"
36
+ # GridStore.open(database, 'filename', 'r') do |f|
37
+ # puts f.read
38
+ # end
39
+ #
40
+ # # Add text to the grid store.
41
+ # GridStore.open(database, 'filename', 'w+') do |f|
42
+ # f.puts "But wait, there's more!"
43
+ # end
44
+ #
45
+ # # Retrieve everything, outputting "Hello, world!\nBut wait, there's more!\n"
46
+ # GridStore.open(database, 'filename', 'r') do |f|
47
+ # puts f.read
48
+ # end
42
49
  class GridStore
43
50
 
44
51
  DEFAULT_ROOT_COLLECTION = 'fs'
@@ -70,80 +77,128 @@ module GridFS
70
77
 
71
78
  attr_reader :md5
72
79
 
73
- class << self
74
-
75
- def exist?(db, name, root_collection=DEFAULT_ROOT_COLLECTION)
76
- db.collection("#{root_collection}.files").find({'filename' => name}).next_document != nil
77
- end
80
+ # Determine whether a given file exists in the GridStore.
81
+ #
82
+ # @param [Mongo::DB] a MongoDB database.
83
+ # @param [String] name the filename.
84
+ # @param [String] root_collection the name of the gridfs root collection.
85
+ #
86
+ # @return [Boolean]
87
+ def self.exist?(db, name, root_collection=DEFAULT_ROOT_COLLECTION)
88
+ db.collection("#{root_collection}.files").find({'filename' => name}).next_document != nil
89
+ end
78
90
 
79
- def open(db, name, mode, options={})
80
- gs = self.new(db, name, mode, options)
81
- result = nil
82
- begin
83
- result = yield gs if block_given?
84
- ensure
85
- gs.close
86
- end
87
- result
91
+ # Open a GridFS file for reading, writing, or appending. Note that
92
+ # this method must be used with a block.
93
+ #
94
+ # @param [Mongo::DB] a MongoDB database.
95
+ # @param [String] name the filename.
96
+ # @param [String] mode one of 'r', 'w', or 'w+' for reading, writing,
97
+ # and appending, respectively.
98
+ # @param [Hash] options any of the options available on
99
+ # GridStore initialization.
100
+ #
101
+ # @see GridStore#initialize.
102
+ # @see The various GridStore class methods, e.g., GridStore.open, GridStore.read etc.
103
+ def self.open(db, name, mode, options={})
104
+ gs = self.new(db, name, mode, options)
105
+ result = nil
106
+ begin
107
+ result = yield gs if block_given?
108
+ ensure
109
+ gs.close
88
110
  end
111
+ result
112
+ end
89
113
 
90
- def read(db, name, length=nil, offset=nil)
91
- GridStore.open(db, name, 'r') { |gs|
92
- gs.seek(offset) if offset
93
- gs.read(length)
94
- }
114
+ # Read a file stored in GridFS.
115
+ #
116
+ # @param [Mongo::DB] db a MongoDB database.
117
+ # @param [String] name the name of the file.
118
+ # @param [Integer] length the number of bytes to read.
119
+ # @param [Integer] offset the number of bytes beyond the
120
+ # beginning of the file to start reading.
121
+ #
122
+ # @return [String] the file data
123
+ def self.read(db, name, length=nil, offset=nil)
124
+ GridStore.open(db, name, 'r') do |gs|
125
+ gs.seek(offset) if offset
126
+ gs.read(length)
95
127
  end
128
+ end
96
129
 
97
- # List the contents of all GridFS files stored in the given db and
98
- # root collection.
99
- #
100
- # :db :: the database to use
101
- #
102
- # :root_collection :: the root collection to use. If not specified, will use default root collection.
103
- def list(db, root_collection=DEFAULT_ROOT_COLLECTION)
104
- db.collection("#{root_collection}.files").find().map { |f|
105
- f['filename']
106
- }
130
+ # List the contents of all GridFS files stored in the given db and
131
+ # root collection.
132
+ #
133
+ # @param [Mongo::DB] db a MongoDB database.
134
+ # @param [String] root_collection the name of the root collection.
135
+ #
136
+ # @return [Array]
137
+ def self.list(db, root_collection=DEFAULT_ROOT_COLLECTION)
138
+ db.collection("#{root_collection}.files").find().map do |f|
139
+ f['filename']
107
140
  end
141
+ end
108
142
 
109
- def readlines(db, name, separator=$/)
110
- GridStore.open(db, name, 'r') { |gs|
111
- gs.readlines(separator)
112
- }
143
+ # Get each line of data from the specified file
144
+ # as an array of strings.
145
+ #
146
+ # @param [Mongo::DB] db a MongoDB database.
147
+ # @param [String] name the filename.
148
+ # @param [String, Reg] separator
149
+ #
150
+ # @return [Array]
151
+ def self.readlines(db, name, separator=$/)
152
+ GridStore.open(db, name, 'r') do |gs|
153
+ gs.readlines(separator)
113
154
  end
155
+ end
114
156
 
115
- def unlink(db, *names)
116
- names.each { |name|
117
- gs = GridStore.new(db, name)
118
- gs.send(:delete_chunks)
119
- gs.collection.remove('_id' => gs.files_id)
120
- }
157
+ # Remove one for more files from the given db.
158
+ #
159
+ # @param [Mongo::Database] db a MongoDB database.
160
+ # @param [Array<String>] names the filenames to remove
161
+ #
162
+ # @return [True]
163
+ def self.unlink(db, *names)
164
+ names.each do |name|
165
+ gs = GridStore.new(db, name)
166
+ gs.send(:delete_chunks)
167
+ gs.collection.remove('_id' => gs.files_id)
121
168
  end
169
+ end
170
+ class << self
122
171
  alias_method :delete, :unlink
123
-
124
172
  end
125
173
 
126
- #---
127
- # ================================================================
128
- #+++
174
+ # Rename a file in this collection. Note that this method uses
175
+ # Collection#update, which means that you will not be notified
176
+ #
177
+ # @param [Mongo::DB] a MongoDB database.
178
+ # @param [String] src the name of the source file.
179
+ # @param [String] dest the name of the destination file.
180
+ # @param [String] root_collection the name of the default root collection.
181
+ def self.mv(db, src, dest, root_collection=DEFAULT_ROOT_COLLECTION)
182
+ db.collection("#{root_collection}.files").update({ :filename => src }, { '$set' => { :filename => dest } })
183
+ end
129
184
 
130
- # Mode may only be 'r', 'w', or 'w+'.
185
+ # Initialize a GridStore instance for reading, writing, or modifying a given file.
186
+ # Note that it's often easier to work with the various GridStore class methods (open, read, etc.).
131
187
  #
132
- # Options. Descriptions start with a list of the modes for which that
133
- # option is legitimate.
188
+ # @param [Mongo::DB] db a MongoDB database.
189
+ # @param [String] name a filename.
190
+ # @param [String] mode either 'r', 'w', or 'w+' for reading, writing, or appending, respectively.
134
191
  #
135
- # :root :: (r, w, w+) Name of root collection to use, instead of
136
- # DEFAULT_ROOT_COLLECTION.
192
+ # @option options [String] :root DEFAULT_ROOT_COLLECTION ('r', 'w', 'w+') the name of the root collection to use.
137
193
  #
138
- # :metadata:: (w, w+) A hash containing any data you want persisted as
139
- # this file's metadata. See also metadata=
194
+ # @option options [String] :metadata ({}) (w, w+) A hash containing any data you want persisted as
195
+ # this file's metadata.
140
196
  #
141
- # :chunk_size :: (w) Sets chunk size for files opened for writing
142
- # See also chunk_size= which may only be called before
143
- # any data is written.
197
+ # @option options [Integer] :chunk_size (Chunk::DEFAULT_CHUNK_SIZE) (w) Sets chunk size for files opened for writing.
198
+ # See also GridStore#chunk_size=.
144
199
  #
145
- # :content_type :: (w) Default value is DEFAULT_CONTENT_TYPE. See
146
- # also #content_type=
200
+ # @option options [String] :content_type ('text/plain') Set the content type stored as the
201
+ # file's metadata. See also GridStore#content_type=.
147
202
  def initialize(db, name, mode='r', options={})
148
203
  @db, @filename, @mode = db, name, mode
149
204
  @root = options[:root] || DEFAULT_ROOT_COLLECTION
@@ -191,18 +246,26 @@ module GridFS
191
246
  @pushback_byte = nil
192
247
  end
193
248
 
249
+ # Get the files collection referenced by this GridStore instance.
250
+ #
251
+ # @return [Mongo::Collection]
194
252
  def collection
195
253
  @db.collection("#{@root}.files")
196
254
  end
197
255
 
198
- # Returns collection used for storing chunks. Depends on value of
199
- # @root.
256
+ # Get the chunk collection referenced by this GridStore.
257
+ #
258
+ # @return [Mongo::Collection]
200
259
  def chunk_collection
201
260
  @db.collection("#{@root}.chunks")
202
261
  end
203
262
 
204
- # Change chunk size. Can only change if the file is opened for write
263
+ # Change the chunk size. This is permitted only when the file is opened for write
205
264
  # and no data has yet been written.
265
+ #
266
+ # @param [Integer] size the new chunk size, in bytes.
267
+ #
268
+ # @return [Integer] the new chunk size.
206
269
  def chunk_size=(size)
207
270
  unless @mode[0] == ?w && @position == 0 && @upload_date == nil
208
271
  raise "error: can only change chunk size if open for write and no data written."
@@ -210,9 +273,7 @@ module GridFS
210
273
  @chunk_size = size
211
274
  end
212
275
 
213
- #---
214
276
  # ================ reading ================
215
- #+++
216
277
 
217
278
  def getc
218
279
  if @pushback_byte
@@ -245,17 +306,6 @@ module GridFS
245
306
  str
246
307
  end
247
308
 
248
- def old_read(len=nil, buf=nil)
249
- buf ||= ''
250
- byte = self.getc
251
- while byte != nil && (len == nil || len > 0)
252
- buf << byte.chr
253
- len -= 1 if len
254
- byte = self.getc if (len == nil || len > 0)
255
- end
256
- buf
257
- end
258
-
259
309
  def read(len=nil, buf=nil)
260
310
  if len
261
311
  read_partial(len, buf)
@@ -302,9 +352,7 @@ module GridFS
302
352
  @position -= 1
303
353
  end
304
354
 
305
- #---
306
355
  # ================ writing ================
307
- #+++
308
356
 
309
357
  def putc(byte)
310
358
  if @curr_chunk.pos == @chunk_size
@@ -344,6 +392,10 @@ module GridFS
344
392
 
345
393
  def write(string)
346
394
  raise "#@filename not opened for write" unless @mode[0] == ?w
395
+ # Since Ruby 1.9.1 doesn't necessarily store one character per byte.
396
+ if string.respond_to?(:force_encoding)
397
+ string.force_encoding("binary")
398
+ end
347
399
  to_write = string.length
348
400
  while (to_write > 0) do
349
401
  if @curr_chunk && @curr_chunk.data.position == @chunk_size
@@ -363,9 +415,7 @@ module GridFS
363
415
  def flush
364
416
  end
365
417
 
366
- #---
367
418
  # ================ status ================
368
- #+++
369
419
 
370
420
  def eof
371
421
  raise IOError.new("stream not open for reading") unless @mode[0] == ?r
@@ -373,9 +423,7 @@ module GridFS
373
423
  end
374
424
  alias_method :eof?, :eof
375
425
 
376
- #---
377
426
  # ================ positioning ================
378
- #+++
379
427
 
380
428
  def rewind
381
429
  if @curr_chunk.chunk_number != 0
@@ -18,7 +18,10 @@ require 'mongo/util/byte_buffer'
18
18
 
19
19
  module Mongo
20
20
 
21
- # An array of binary bytes with a Mongo subtype value.
21
+ # An array of binary bytes with a MongoDB subtype. See the subtype
22
+ # constants for reference.
23
+ #
24
+ # Use this class when storing binary data in documents.
22
25
  class Binary < ByteBuffer
23
26
 
24
27
  SUBTYPE_BYTES = 0x02
@@ -29,6 +32,13 @@ module Mongo
29
32
  # One of the SUBTYPE_* constants. Default is SUBTYPE_BYTES.
30
33
  attr_accessor :subtype
31
34
 
35
+ # Create a buffer for storing binary data in MongoDB.
36
+ #
37
+ # @param [Array] initia_data
38
+ # @param [Fixnum] one of four values specifying a BSON binary subtype. Possible values are
39
+ # SUBTYPE_BYTES, SUBTYPE_UUID, SUBTYPE_MD5, and SUBTYPE_USER_DEFINED.
40
+ #
41
+ # @see http://www.mongodb.org/display/DOCS/BSON#BSON-noteondatabinary BSON binary subtypes.
32
42
  def initialize(initial_data=[], subtype=SUBTYPE_BYTES)
33
43
  super(initial_data)
34
44
  @subtype = subtype
@@ -16,12 +16,17 @@
16
16
 
17
17
  module Mongo
18
18
 
19
- # JavaScript code to be evaluated by MongoDB
19
+ # JavaScript code to be evaluated by MongoDB.
20
20
  class Code < String
21
21
 
22
22
  # Hash mapping identifiers to their values
23
23
  attr_accessor :scope
24
24
 
25
+ # Wrap code to be evaluated by MongoDB.
26
+ #
27
+ # @param [String] code the JavaScript code.
28
+ # @param [Hash] a document mapping identifiers to values, which
29
+ # represent the scope in which the code is to be executed.
25
30
  def initialize(code, scope={})
26
31
  super(code)
27
32
  @scope = scope
@@ -16,13 +16,18 @@
16
16
 
17
17
  module Mongo
18
18
 
19
+ # A reference to another object in a MongoDB database.
19
20
  class DBRef
20
21
 
21
22
  attr_reader :namespace, :object_id
22
23
 
24
+ # Create a DBRef. Use this class in conjunction with DB#dereference.
25
+ #
26
+ # @param [String] a collection name
27
+ # @param [ObjectID] an object id
23
28
  def initialize(namespace, object_id)
24
- @namespace, @object_id =
25
- namespace, object_id
29
+ @namespace = namespace
30
+ @object_id = object_id
26
31
  end
27
32
 
28
33
  def to_s
@@ -0,0 +1,58 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 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
+
19
+ # A class representing the BSON MaxKey type. MaxKey will always compare greater than
20
+ # all other BSON types and values.
21
+ #
22
+ # @example Sorting (assume @numbers is a collection):
23
+ #
24
+ # >> @numbers.save({"n" => Mongo::MaxKey.new})
25
+ # >> @numbers.save({"n" => 0})
26
+ # >> @numbers.save({"n" => 5_000_000})
27
+ # >> @numbers.find.sort("n").to_a
28
+ # => [{"_id"=>4b5a050c238d3bace2000004, "n"=>0},
29
+ # {"_id"=>4b5a04e6238d3bace2000002, "n"=>5_000_000},
30
+ # {"_id"=>4b5a04ea238d3bace2000003, "n"=>#<Mongo::MaxKey:0x1014ef410>},
31
+ # ]
32
+ class MaxKey
33
+
34
+ def ==(obj)
35
+ obj.class == MaxKey
36
+ end
37
+ end
38
+
39
+ # A class representing the BSON MinKey type. MinKey will always compare less than
40
+ # all other BSON types and values.
41
+ #
42
+ # @example Sorting (assume @numbers is a collection):
43
+ #
44
+ # >> @numbers.save({"n" => Mongo::MinKey.new})
45
+ # >> @numbers.save({"n" => -1_000_000})
46
+ # >> @numbers.save({"n" => 1_000_000})
47
+ # >> @numbers.find.sort("n").to_a
48
+ # => [{"_id"=>4b5a050c238d3bace2000004, "n"=>#<Mongo::MinKey:0x1014ef410>},
49
+ # {"_id"=>4b5a04e6238d3bace2000002, "n"=>-1_000_000},
50
+ # {"_id"=>4b5a04ea238d3bace2000003, "n"=>1_000_000},
51
+ # ]
52
+ class MinKey
53
+
54
+ def ==(obj)
55
+ obj.class == MinKey
56
+ end
57
+ end
58
+ end