pahagon-mongo-abd 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/README.rdoc +353 -0
  2. data/Rakefile +62 -0
  3. data/bin/bson_benchmark.rb +59 -0
  4. data/bin/mongo_console +21 -0
  5. data/bin/run_test_script +19 -0
  6. data/bin/standard_benchmark +109 -0
  7. data/examples/admin.rb +41 -0
  8. data/examples/benchmarks.rb +42 -0
  9. data/examples/blog.rb +76 -0
  10. data/examples/capped.rb +23 -0
  11. data/examples/cursor.rb +47 -0
  12. data/examples/gridfs.rb +87 -0
  13. data/examples/index_test.rb +125 -0
  14. data/examples/info.rb +30 -0
  15. data/examples/queries.rb +69 -0
  16. data/examples/simple.rb +23 -0
  17. data/examples/strict.rb +34 -0
  18. data/examples/types.rb +35 -0
  19. data/lib/mongo.rb +19 -0
  20. data/lib/mongo/admin.rb +83 -0
  21. data/lib/mongo/collection.rb +415 -0
  22. data/lib/mongo/connection.rb +151 -0
  23. data/lib/mongo/cursor.rb +279 -0
  24. data/lib/mongo/db.rb +560 -0
  25. data/lib/mongo/errors.rb +26 -0
  26. data/lib/mongo/gridfs.rb +16 -0
  27. data/lib/mongo/gridfs/chunk.rb +92 -0
  28. data/lib/mongo/gridfs/grid_store.rb +464 -0
  29. data/lib/mongo/message.rb +20 -0
  30. data/lib/mongo/message/get_more_message.rb +32 -0
  31. data/lib/mongo/message/insert_message.rb +37 -0
  32. data/lib/mongo/message/kill_cursors_message.rb +31 -0
  33. data/lib/mongo/message/message.rb +80 -0
  34. data/lib/mongo/message/message_header.rb +45 -0
  35. data/lib/mongo/message/msg_message.rb +29 -0
  36. data/lib/mongo/message/opcodes.rb +27 -0
  37. data/lib/mongo/message/query_message.rb +78 -0
  38. data/lib/mongo/message/remove_message.rb +37 -0
  39. data/lib/mongo/message/update_message.rb +38 -0
  40. data/lib/mongo/query.rb +118 -0
  41. data/lib/mongo/types/binary.rb +38 -0
  42. data/lib/mongo/types/code.rb +30 -0
  43. data/lib/mongo/types/dbref.rb +33 -0
  44. data/lib/mongo/types/objectid.rb +143 -0
  45. data/lib/mongo/types/regexp_of_holding.rb +40 -0
  46. data/lib/mongo/util/bson.rb +546 -0
  47. data/lib/mongo/util/byte_buffer.rb +167 -0
  48. data/lib/mongo/util/ordered_hash.rb +113 -0
  49. data/lib/mongo/util/xml_to_ruby.rb +105 -0
  50. data/mongo-ruby-driver.gemspec +103 -0
  51. data/test/mongo-qa/_common.rb +8 -0
  52. data/test/mongo-qa/admin +26 -0
  53. data/test/mongo-qa/capped +22 -0
  54. data/test/mongo-qa/count1 +18 -0
  55. data/test/mongo-qa/dbs +22 -0
  56. data/test/mongo-qa/find +10 -0
  57. data/test/mongo-qa/find1 +15 -0
  58. data/test/mongo-qa/gridfs_in +16 -0
  59. data/test/mongo-qa/gridfs_out +17 -0
  60. data/test/mongo-qa/indices +49 -0
  61. data/test/mongo-qa/remove +25 -0
  62. data/test/mongo-qa/stress1 +35 -0
  63. data/test/mongo-qa/test1 +11 -0
  64. data/test/mongo-qa/update +18 -0
  65. data/test/test_admin.rb +69 -0
  66. data/test/test_bson.rb +268 -0
  67. data/test/test_byte_buffer.rb +69 -0
  68. data/test/test_chunk.rb +84 -0
  69. data/test/test_collection.rb +249 -0
  70. data/test/test_connection.rb +101 -0
  71. data/test/test_cursor.rb +331 -0
  72. data/test/test_db.rb +185 -0
  73. data/test/test_db_api.rb +798 -0
  74. data/test/test_db_connection.rb +18 -0
  75. data/test/test_grid_store.rb +284 -0
  76. data/test/test_message.rb +35 -0
  77. data/test/test_objectid.rb +105 -0
  78. data/test/test_ordered_hash.rb +138 -0
  79. data/test/test_round_trip.rb +120 -0
  80. data/test/test_threading.rb +37 -0
  81. metadata +135 -0
@@ -0,0 +1,353 @@
1
+ = Introduction
2
+
3
+ This is a Ruby driver for MongoDB[http://www.mongodb.org].
4
+
5
+ Here is a quick code sample. See the files in the "examples" subdirectory for
6
+ many more.
7
+
8
+ require 'mongo'
9
+
10
+ include Mongo
11
+
12
+ db = Connection.new('localhost').db('sample-db')
13
+ coll = db.collection('test')
14
+
15
+ coll.clear
16
+ 3.times { |i| coll.insert({'a' => i+1}) }
17
+ puts "There are #{coll.count()} records. Here they are:"
18
+ coll.find().each { |doc| puts doc.inspect }
19
+
20
+ This driver also includes an implementation of a GridStore class, a Ruby
21
+ interface to Mongo's GridFS storage.
22
+
23
+ = Installation
24
+
25
+ Install the "mongo" gem by typing
26
+
27
+ $ gem sources -a http://gems.github.com
28
+ $ sudo gem install mongodb-mongo
29
+
30
+ The first line tells RubyGems to add the GitHub gem repository. You only need
31
+ to run this command once.
32
+
33
+ === From the GitHub source
34
+
35
+ The source code is available at http://github.com/mongodb/mongo-ruby-driver.
36
+ You can either clone the git repository or download a tarball or zip file.
37
+ Once you have the source, you can use it from wherever you downloaded it or
38
+ you can install it as a gem from the source by typing
39
+
40
+ $ rake gem:install
41
+
42
+ Note: when you install the gem this way it is called "mongo", not
43
+ "mongodb-mongo". In either case, you "require 'mongo'" in your source code.
44
+
45
+ === Optional C Extension
46
+
47
+ There is a separate gem containing optional C extensions that will increase the
48
+ performance of the driver. To use the optional extensions just install the gem
49
+ by typing
50
+
51
+ $ sudo gem install mongodb-mongo_ext
52
+
53
+ To install from source type this instead
54
+
55
+ $ rake gem:install_extensions
56
+
57
+ That's all there is to it!
58
+
59
+ = Examples
60
+
61
+ There are many examples in the "examples" subdirectory. Samples include using
62
+ the driver and using the GridFS class GridStore. Mongo must be running for
63
+ these examples to work, of course.
64
+
65
+ Here's how to start mongo and run the "simple.rb" example:
66
+
67
+ $ cd path/to/mongo
68
+ $ ./mongod run
69
+ ... then in another window ...
70
+ $ cd path/to/mongo-ruby-driver
71
+ $ ruby examples/simple.rb
72
+
73
+ See also the test code, especially test/test_db_api.rb.
74
+
75
+ = The Driver
76
+
77
+ Here is some simple example code:
78
+
79
+ require 'rubygems' # not required for Ruby 1.9
80
+ require 'mongo'
81
+
82
+ include Mongo
83
+ db = Connection.new.db('my-db-name')
84
+ things = db.collection('things')
85
+
86
+ things.clear
87
+ things.insert('a' => 42)
88
+ things.insert('a' => 99, 'b' => Time.now)
89
+ puts things.count # => 2
90
+ puts things.find('a' => 42).next_object.inspect # {"a"=>42}
91
+
92
+
93
+ = GridStore
94
+
95
+ The GridStore class is a Ruby implementation of Mongo's GridFS file storage
96
+ system. An instance of GridStore is like an IO object. See the rdocs for
97
+ details, and see examples/gridfs.rb for code that uses many of the GridStore
98
+ features like metadata, content type, rewind/seek/tell, etc.
99
+
100
+ Note that the GridStore class is not automatically required when you require
101
+ 'mongo'. You need to require 'mongo/gridfs'.
102
+
103
+ Example code:
104
+
105
+ GridStore.open(database, 'filename', 'w') { |f|
106
+ f.puts "Hello, world!"
107
+ }
108
+ GridStore.open(database, 'filename, 'r') { |f|
109
+ puts f.read # => Hello, world!\n
110
+ }
111
+ GridStore.open(database, 'filename', 'w+') { |f|
112
+ f.puts "But wait, there's more!"
113
+ }
114
+ GridStore.open(database, 'filename, 'r') { |f|
115
+ puts f.read # => Hello, world!\nBut wait, there's more!\n
116
+ }
117
+
118
+
119
+
120
+ = Notes
121
+
122
+ == Using with Phusion Passenger
123
+
124
+ When passenger is in smart spawning mode you need to be sure that child
125
+ processes forked by passenger will create a new connection to the database.
126
+ activerecord-mongo-adapter handles this for you, so if you are using that
127
+ you shouldn't need to worry about it. Otherwise you'll either need to use
128
+ conservative spawning[http://www.modrails.org/documentation/Users%20guide.html#RailsSpawnMethod]
129
+ or handle reconnecting when passenger forks a new process:
130
+
131
+ if defined?(PhusionPassenger)
132
+ PhusionPassenger.on_event(:starting_worker_process) do |forked|
133
+ if forked
134
+ # Call db.connect_to_master to reconnect here
135
+ end
136
+ end
137
+ end
138
+
139
+ The above code should be put in _environment.rb_ or an initialization
140
+ script.
141
+
142
+ See this thread[http://groups.google.com/group/mongodb-user/browse_thread/thread/f31e2d23de38136a]
143
+ for more details on this issue.
144
+
145
+ == String Encoding
146
+
147
+ The BSON ("Binary JSON") format used to communicate with Mongo requires that
148
+ strings be UTF-8 (http://en.wikipedia.org/wiki/UTF-8).
149
+
150
+ Ruby 1.9 has built-in character encoding support. All strings sent to Mongo
151
+ and received from Mongo are converted to UTF-8 when necessary, and strings
152
+ read from Mongo will have their character encodings set to UTF-8.
153
+
154
+ When used with Ruby 1.8, the bytes in each string are written to and read from
155
+ Mongo as-is. If the string is ASCII all is well, because ASCII is a subset of
156
+ UTF-8. If the string is not ASCII then it may not be a well-formed UTF-8
157
+ string.
158
+
159
+ == Primary Keys
160
+
161
+ The field _id is a primary key. It is treated specially by the database, and
162
+ its use makes many operations more efficient. The value of an _id may be of
163
+ any type. The database itself inserts an _id value if none is specified when
164
+ a record is inserted.
165
+
166
+ === Primary Key Factories
167
+
168
+ A primary key factory is a class you supply to a DB object that knows how to
169
+ generate _id values. If you want to control _id values or even their types,
170
+ using a PK factory lets you do so.
171
+
172
+ You can tell the Ruby Mongo driver how to create primary keys by passing in
173
+ the :pk option to the Connection#db method.
174
+
175
+ include Mongo
176
+ db = Connection.new.db('dbname', :pk => MyPKFactory.new)
177
+
178
+ A primary key factory object must respond to :create_pk, which should take a
179
+ hash and return a hash which merges the original hash with any primary key
180
+ fields the factory wishes to inject. NOTE: if the object already has a primary
181
+ key, the factory should not inject a new key; this means that the object is
182
+ being used in a repsert but it already exists. The idea here is that whenever
183
+ a record is inserted, the :pk object's +create_pk+ method will be called and
184
+ the new hash returned will be inserted.
185
+
186
+ Here is a sample primary key factory, taken from the tests:
187
+
188
+ class TestPKFactory
189
+ def create_pk(row)
190
+ row['_id'] ||= Mongo::ObjectID.new
191
+ row
192
+ end
193
+ end
194
+
195
+ Here's a slightly more sophisticated one that handles both symbol and string
196
+ keys. This is the PKFactory that comes with the MongoRecord code (an
197
+ ActiveRecord-like framework for non-Rails apps) and the AR Mongo adapter code
198
+ (for Rails):
199
+
200
+ class PKFactory
201
+ def create_pk(row)
202
+ return row if row[:_id]
203
+ row.delete(:_id) # in case it exists but the value is nil
204
+ row['_id'] ||= Mongo::ObjectID.new
205
+ row
206
+ end
207
+ end
208
+
209
+ A database's PK factory object may be set either when a DB object is created
210
+ or immediately after you obtain it, but only once. The only reason it is
211
+ changeable at all is so that libraries such as MongoRecord that use this
212
+ driver can set the PK factory after obtaining the database but before using it
213
+ for the first time.
214
+
215
+ == The DB Class
216
+
217
+ === Primary Key factories
218
+
219
+ See the section on "Primary Keys" above.
220
+
221
+ === Strict mode
222
+
223
+ Each database has an optional strict mode. If strict mode is on, then asking
224
+ for a collection that does not exist will raise an error, as will asking to
225
+ create a collection that already exists. Note that both these operations are
226
+ completely harmless; strict mode is a programmer convenience only.
227
+
228
+ To turn on strict mode, either pass in :strict => true when obtaining a DB
229
+ object or call the :strict= method:
230
+
231
+ db = Connection.new.db('dbname', :strict => true)
232
+ # I'm feeling lax
233
+ db.strict = false
234
+ # No, I'm not!
235
+ db.strict = true
236
+
237
+ The method DB#strict? returns the current value of that flag.
238
+
239
+ == Cursors
240
+
241
+ Random cursor fun facts:
242
+
243
+ - Cursors are enumerable.
244
+
245
+ - The query doesn't get run until you actually attempt to retrieve data from a
246
+ cursor.
247
+
248
+ - Cursors have a to_a method.
249
+
250
+
251
+
252
+ = Testing
253
+
254
+ If you have the source code, you can run the tests.
255
+
256
+ $ rake test
257
+
258
+ The tests assume that the Mongo database is running on the default port. You
259
+ can override the default host (localhost) and port (Connection::DEFAULT_PORT) by
260
+ using the environment variables MONGO_RUBY_DRIVER_HOST and
261
+ MONGO_RUBY_DRIVER_PORT.
262
+
263
+ The project mongo-qa (http://github.com/mongodb/mongo-qa) contains many more
264
+ Mongo driver tests that are language independent. To run thoses tests as part
265
+ of the "rake test" task, download the code "next to" this directory. So, after
266
+ installing the mongo-qa code you would have these two directories next to each
267
+ other:
268
+
269
+ $ ls
270
+ mongo-qa
271
+ mongo-ruby-driver
272
+ $ rake test
273
+
274
+ The tests run just fine if the mongo-qa directory is not there.
275
+
276
+ Additionally, the script bin/validate is used by the mongo-qa project's
277
+ validator script.
278
+
279
+
280
+ = Documentation
281
+
282
+ This documentation is available online at http://api.mongodb.org/ruby. You can
283
+ generate the documentation if you have the source by typing
284
+
285
+ $ rake rdoc
286
+
287
+ Then open the file html/index.html.
288
+
289
+
290
+ = Release Notes
291
+
292
+ See the git log comments.
293
+
294
+ = Credits
295
+
296
+ Adrian Madrid, aemadrid@gmail.com
297
+ * bin/mongo_console
298
+ * examples/benchmarks.rb
299
+ * examples/irb.rb
300
+ * Modifications to examples/simple.rb
301
+ * Found plenty of bugs and missing features.
302
+ * Ruby 1.9 support.
303
+ * Gem support.
304
+ * Many other code suggestions and improvements.
305
+
306
+ Aman Gupta, aman@tmm1.net
307
+ * Collection#save
308
+
309
+ Jon Crosby, jon@joncrosby.me
310
+ * Some code clean-up
311
+
312
+ John Nunemaker, http://railstips.org
313
+ * Collection#create_index takes symbols as well as strings
314
+ * Fix for Collection#save
315
+
316
+ David James, djames@sunlightfoundation.com
317
+ * Fix dates to return as UTC
318
+
319
+ Paul Dlug, paul.dlug@gmail.com
320
+ * Generate _id on the client side if not provided
321
+ * Collection#insert and Collection#save return _id
322
+
323
+ Durran Jordan and Les Hill, durran@gmail.com
324
+ * DB#collections
325
+
326
+ Cyril Mougel, cyril.mougel@gmail.com
327
+ * Initial logging support
328
+
329
+ Jack Chen, chendo on github
330
+ * Test case + fix for deserializing pre-epoch Time instances
331
+
332
+ Kyle Banker, banker on github
333
+ * #limit and #skip methods for Cursor instances
334
+
335
+ Michael Bernstein, mrb on github
336
+ * #sort method for Cursor instances
337
+
338
+ = License
339
+
340
+ Copyright 2008-2009 10gen Inc.
341
+
342
+ Licensed under the Apache License, Version 2.0 (the "License");
343
+ you may not use this file except in compliance with the License.
344
+ You may obtain a copy of the License at
345
+
346
+ http://www.apache.org/licenses/LICENSE-2.0
347
+
348
+ Unless required by applicable law or agreed to in writing, software
349
+ distributed under the License is distributed on an "AS IS" BASIS,
350
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
351
+ See the License for the specific language governing permissions and
352
+ limitations under the License.
353
+
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'rubygems/specification'
3
+ require 'fileutils'
4
+ require 'rake'
5
+ require 'rake/testtask'
6
+ require 'rake/gempackagetask'
7
+ begin
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ rescue LoadError
10
+ end
11
+ require 'rbconfig'
12
+ include Config
13
+
14
+ gem_command = "gem"
15
+ gem_command = "gem1.9" if $0.match(/1\.9$/) # use gem1.9 if we used rake1.9
16
+
17
+ # NOTE: some of the tests assume Mongo is running
18
+ Rake::TestTask.new do |t|
19
+ t.test_files = FileList['test/test*.rb']
20
+ end
21
+
22
+ desc "Generate documentation"
23
+ task :rdoc do
24
+ version = eval(File.read("mongo-ruby-driver.gemspec")).version
25
+ out = File.join('html', version.to_s)
26
+ FileUtils.rm_rf('html')
27
+ system "rdoc --main README.rdoc --op #{out} --inline-source --quiet README.rdoc `find lib -name '*.rb'`"
28
+ end
29
+
30
+ desc "Publish documentation to mongo.rubyforge.org"
31
+ task :publish => [:rdoc] do
32
+ # Assumes docs are in ./html
33
+ Rake::RubyForgePublisher.new(GEM, RUBYFORGE_USER).upload
34
+ end
35
+
36
+ namespace :gem do
37
+
38
+ desc "Install the gem locally"
39
+ task :install do
40
+ sh <<EOS
41
+ #{gem_command} build mongo-ruby-driver.gemspec &&
42
+ sudo #{gem_command} install mongo-*.gem &&
43
+ rm mongo-*.gem
44
+ EOS
45
+ end
46
+
47
+ desc "Install the optional c extensions"
48
+ task :install_extensions do
49
+ sh <<EOS
50
+ #{gem_command} build mongo-extensions.gemspec &&
51
+ sudo #{gem_command} install mongo_ext-*.gem &&
52
+ rm mongo_ext-*.gem
53
+ EOS
54
+ end
55
+
56
+ end
57
+
58
+ task :default => :list
59
+
60
+ task :list do
61
+ system 'rake -T'
62
+ end
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
4
+ require 'mongo'
5
+
6
+ include Mongo
7
+
8
+ TRIALS = 100000
9
+
10
+ def encode(doc)
11
+ t0 = Time.new
12
+ b = BSON.new
13
+ TRIALS.times { |i|
14
+ b = BSON.new
15
+ b.serialize doc
16
+ }
17
+ print "took: #{Time.now.to_f - t0.to_f}\n"
18
+ return b
19
+ end
20
+
21
+ def decode(bson)
22
+ t0 = Time.new
23
+ doc = nil
24
+ TRIALS.times { |i|
25
+ doc = bson.deserialize
26
+ }
27
+ print "took: #{Time.now.to_f - t0.to_f}\n"
28
+ return doc
29
+ end
30
+
31
+ TEST_CASES = [{},
32
+ {
33
+ "hello" => "world"
34
+ },
35
+ {
36
+ "hello" => "world",
37
+ "mike" => "something",
38
+ "here's" => "another"
39
+ },
40
+ {
41
+ "int" => 200,
42
+ "bool" => true,
43
+ "an int" => 20,
44
+ "a bool" => false
45
+ },
46
+ {
47
+ "this" => 5,
48
+ "is" => {"a" => true},
49
+ "big" => [true, 5.5],
50
+ "object" => nil
51
+ }]
52
+
53
+ TEST_CASES.each { |doc|
54
+ print "case #{doc.inspect}\n"
55
+ print "enc bson\n"
56
+ enc_bson = encode(doc)
57
+ print "dec bson\n"
58
+ raise "FAIL" unless doc == decode(enc_bson)
59
+ }