mongo 0.18.2 → 0.18.3

Sign up to get free protection for your applications and to get access to all the features.
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