mongo 1.6.1 → 1.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/README.md +17 -16
  2. data/Rakefile +30 -24
  3. data/docs/HISTORY.md +10 -0
  4. data/docs/RELEASES.md +7 -0
  5. data/docs/REPLICA_SETS.md +2 -2
  6. data/docs/TUTORIAL.md +181 -84
  7. data/lib/mongo.rb +0 -3
  8. data/lib/mongo/collection.rb +1 -1
  9. data/lib/mongo/connection.rb +28 -20
  10. data/lib/mongo/db.rb +5 -3
  11. data/lib/mongo/exceptions.rb +1 -1
  12. data/lib/mongo/gridfs/grid_file_system.rb +1 -1
  13. data/lib/mongo/networking.rb +18 -18
  14. data/lib/mongo/repl_set_connection.rb +24 -3
  15. data/lib/mongo/util/node.rb +6 -16
  16. data/lib/mongo/util/pool.rb +8 -11
  17. data/lib/mongo/util/ssl_socket.rb +34 -12
  18. data/lib/mongo/util/tcp_socket.rb +92 -3
  19. data/lib/mongo/util/uri_parser.rb +2 -2
  20. data/lib/mongo/version.rb +1 -1
  21. data/test/auxillary/repl_set_auth_test.rb +19 -5
  22. data/test/bson/bson_test.rb +23 -21
  23. data/test/bson/json_test.rb +1 -1
  24. data/test/collection_test.rb +14 -4
  25. data/test/connection_test.rb +14 -11
  26. data/test/cursor_test.rb +4 -4
  27. data/test/grid_file_system_test.rb +3 -1
  28. data/test/grid_io_test.rb +2 -2
  29. data/test/grid_test.rb +13 -6
  30. data/test/pool_test.rb +0 -2
  31. data/test/replica_sets/basic_test.rb +1 -1
  32. data/test/replica_sets/complex_connect_test.rb +5 -4
  33. data/test/replica_sets/connect_test.rb +14 -6
  34. data/test/replica_sets/pooled_insert_test.rb +1 -1
  35. data/test/replica_sets/query_test.rb +2 -2
  36. data/test/replica_sets/read_preference_test.rb +1 -2
  37. data/test/replica_sets/refresh_test.rb +4 -2
  38. data/test/replica_sets/refresh_with_threads_test.rb +7 -13
  39. data/test/replica_sets/rs_test_helper.rb +1 -1
  40. data/test/test_helper.rb +6 -4
  41. data/test/threading/threading_with_large_pool_test.rb +1 -1
  42. data/test/threading_test.rb +2 -2
  43. data/test/timeout_test.rb +40 -0
  44. data/test/tools/repl_set_manager.rb +9 -8
  45. data/test/unit/connection_test.rb +6 -7
  46. data/test/unit/node_test.rb +1 -0
  47. data/test/unit/pool_manager_test.rb +2 -1
  48. data/test/uri_test.rb +1 -2
  49. metadata +13 -6
data/README.md CHANGED
@@ -62,7 +62,7 @@ And for a significant performance boost, you'll want to install the C extensions
62
62
  $ gem install bson_ext
63
63
 
64
64
  Note that bson_ext isn't used with JRuby. Instead, some native Java extensions are bundled with the bson gem.
65
- If you ever need to modify these extenions, you can recompile with the following rake task:
65
+ If you ever need to modify these extensions, you can recompile with the following rake task:
66
66
 
67
67
  $ rake build:java
68
68
 
@@ -103,7 +103,7 @@ See also the test code, especially test/test_db_api.rb.
103
103
 
104
104
  The Ruby driver include two abstractions for storing large files: Grid and GridFileSystem.
105
105
  The Grid class is a Ruby implementation of MongoDB's GridFS file storage
106
- specification. GridFileSystem is essentailly the same, but provides a more filesystem-like API
106
+ specification. GridFileSystem is essentially the same, but provides a more filesystem-like API
107
107
  and assumes that filenames are unique.
108
108
 
109
109
  An instance of both classes represents an individual file store. See the API reference
@@ -264,9 +264,22 @@ If implementing higher-level timeouts, using tools like `Rack::Timeout`, it's ve
264
264
  to call `Mongo::Connection#close` to prevent the subsequent operation from receiving the previous
265
265
  request.
266
266
 
267
+ ### Test-Unit, Shoulda, and Mocha
268
+
269
+ Running the test suite requires test-unit, shoulda, and mocha. You can install them as follows:
270
+
271
+ $ gem install test-unit
272
+ $ gem install shoulda
273
+ $ gem install mocha
274
+
275
+ The tests assume that the Mongo database is running on the default port. You
276
+ can override the default host (localhost) and port (Connection::DEFAULT_PORT) by
277
+ using the environment variables MONGO_RUBY_DRIVER_HOST and
278
+ MONGO_RUBY_DRIVER_PORT.
279
+
267
280
  # Testing
268
281
 
269
- If you have the source code, you can run the tests.
282
+ If you have the source code, you can run the tests. Skip this test with the C extension if you're running JRuby.
270
283
 
271
284
  $ rake test:c
272
285
 
@@ -279,7 +292,7 @@ These will run both unit and functional tests. To run these tests alone:
279
292
  $ rake test:unit
280
293
  $ rake test:functional
281
294
 
282
- To run any individual rake tasks with the C extension enabled, just pass C_EXT=true to the task:
295
+ To run any individual rake tasks with the C extension enabled, just pass C_EXT=true to the task (don't do this with JRuby):
283
296
 
284
297
  $ rake test:unit C_EXT=true
285
298
 
@@ -287,18 +300,6 @@ If you want to test replica set, you can run the following task:
287
300
 
288
301
  $ rake test:rs
289
302
 
290
- ### Shoulda and Mocha
291
-
292
- Running the test suite requires shoulda and mocha. You can install them as follows:
293
-
294
- $ gem install shoulda
295
- $ gem install mocha
296
-
297
- The tests assume that the Mongo database is running on the default port. You
298
- can override the default host (localhost) and port (Connection::DEFAULT_PORT) by
299
- using the environment variables MONGO_RUBY_DRIVER_HOST and
300
- MONGO_RUBY_DRIVER_PORT.
301
-
302
303
  # Documentation
303
304
 
304
305
  This documentation is available online at [http://api.mongodb.org/ruby](http://api.mongodb.org/ruby). You can
data/Rakefile CHANGED
@@ -160,7 +160,7 @@ end
160
160
 
161
161
  desc "Generate YARD documentation"
162
162
  task :ydoc do
163
- require 'mongo'
163
+ require './lib/mongo/version.rb'
164
164
  out = File.join('ydoc', Mongo::VERSION)
165
165
  FileUtils.rm_rf('ydoc')
166
166
  system "yardoc lib/**/*.rb lib/mongo/**/*.rb lib/bson/**/*.rb -e ./yard/yard_ext.rb -p yard/templates -o #{out} --title MongoRuby-#{Mongo::VERSION} --files docs/TUTORIAL.md,docs/GridFS.md,docs/FAQ.md,docs/REPLICA_SETS.md,docs/WRITE_CONCERN.md,docs/READ_PREFERENCE.md,docs/HISTORY.md,docs/CREDITS.md,docs/RELEASES.md,docs/CREDITS.md,docs/TAILABLE_CURSORS.md"
@@ -188,7 +188,6 @@ namespace :jenkins do
188
188
  end
189
189
 
190
190
  namespace :gem do
191
-
192
191
  desc "Install the gem locally"
193
192
  task :install do
194
193
  `gem build bson.gemspec`
@@ -212,17 +211,6 @@ namespace :gem do
212
211
  `gem install --no-rdoc --no-ri bson_ext-*.gem`
213
212
  `rm bson_ext-*.gem`
214
213
  end
215
-
216
- desc "Build all gems"
217
- task :build_all do
218
- `rm *.gem`
219
- `gem build mongo.gemspec`
220
- `gem build bson.gemspec`
221
- `gem build bson.java.gemspec`
222
- `gem build bson_ext.gemspec`
223
- puts `ls *.gem`
224
- end
225
-
226
214
  end
227
215
 
228
216
  namespace :ci do
@@ -271,6 +259,7 @@ end
271
259
 
272
260
  def change_version(new_version)
273
261
  version = current_version
262
+ puts "Changing version from #{version} to #{new_version}"
274
263
  VERSION_FILES.each do |filename|
275
264
  f = File.open(filename)
276
265
  str = f.read
@@ -283,30 +272,47 @@ def change_version(new_version)
283
272
  end
284
273
 
285
274
  namespace :deploy do
286
- task :version, [:version] do |t, args|
287
- check_version(args[:version])
288
- puts args[:version]
275
+ desc "Change version to new release"
276
+ task :change_version, [:version] do |t, args|
277
+ check_version(args[:version])
289
278
  change_version(args[:version])
290
279
  end
291
280
 
292
- task :git_prepare, [:version] do |t, args|
281
+ desc "Add version files, commit, tag release"
282
+ task :git_prepare do |t, args|
293
283
  g = Git.open(Dir.getwd())
294
- version = args[:version]
295
- check_version(version)
296
- g.add(VERSION_FILES)
284
+ version = current_version
285
+ to_commit = VERSION_FILES << 'docs/HISTORY.md'
286
+ g.add(to_commit)
297
287
  g.commit "RELEASE #{version}"
298
288
  g.add_tag("#{version}")
299
289
  end
300
290
 
291
+ desc "Push release to github"
301
292
  task :git_push do
302
293
  g = Git.open(Dir.getwd())
303
294
  g.push
304
295
  end
305
296
 
306
- task :gems, [:version] do |t, args|
307
- check_version(args[:version])
308
- check_gem_list_existence(args[:version])
309
- gem_list
297
+ desc "Build all gems"
298
+ task :gem_build do
299
+ `rm *.gem`
300
+ `gem build mongo.gemspec`
301
+ `gem build bson.gemspec`
302
+ `gem build bson.java.gemspec`
303
+ `gem build bson_ext.gemspec`
304
+ puts `ls *.gem`
305
+ end
306
+
307
+ desc "Push all gems to RubyGems"
308
+ task :gem_push do |t, args|
309
+ check_gem_list_existence(current_version)
310
+ gem_list.each do |gem|
311
+ puts "Push #{gem} to RubyGems? (y/N)"
312
+ if gets.chomp! == 'y'
313
+ system "gem push #{gem}"
314
+ end
315
+ end
310
316
  end
311
317
  end
312
318
 
@@ -1,5 +1,15 @@
1
1
  # MongoDB Ruby Driver History
2
2
 
3
+ ### 1.6.2
4
+ 2012-04-05
5
+
6
+ * Implements socket timeouts via non-blocking IO instead of Timeout module
7
+ which should greately increase performance in highly threaded applications
8
+ * Added ability to authentication via secondary if primary node unavailable
9
+ * Replica set refresh interval now enforces a lower bound of 60 seconds
10
+ * Added documentation for dropping indexes, collections, databases
11
+ * Test output cleanup (...)s unless failure occurs
12
+
3
13
  ### 1.6.1
4
14
  2012-03-07
5
15
 
@@ -45,3 +45,10 @@ Before each relese to Rubygems.org, the following steps will be taken:
45
45
  11. Close out release in JIRA.
46
46
 
47
47
  12. Annouce release on mongodb-user and mongodb-dev.
48
+
49
+ ## Rake Deploy Tasks
50
+ 1. rake deploy:change_version[1.6.1]
51
+ 2. rake deploy:git_prepare
52
+ 3. rake deploy:git_push
53
+ 4. rake deploy:gem_build
54
+ 5. rake deploy:gem_push
@@ -41,8 +41,8 @@ the state of any secondary node, the automated refresh will ensure that this sta
41
41
 
42
42
  There are two secenarios in which refresh is helpful and does not raise exceptions:
43
43
 
44
- # You add a new secondary node to an existing replica set
45
- # You remove an unused secondary from an existing replica set
44
+ 1. You add a new secondary node to an existing replica set
45
+ 2. You remove an unused secondary from an existing replica set
46
46
 
47
47
  If using MongoDB earlier than 2.0 any changes to replica set state will raise exceptions therefore refresh mode will not be useful.
48
48
 
@@ -9,8 +9,11 @@ As always, the [latest source for the Ruby driver](http://github.com/mongodb/mon
9
9
  ## Installation
10
10
 
11
11
  The mongo-ruby-driver gem is served through Rubygems.org. To install, make sure you have the latest version of rubygems.
12
+
12
13
  gem update --system
14
+
13
15
  Next, install the mongo rubygem:
16
+
14
17
  gem install mongo
15
18
 
16
19
  The required `bson` gem will be installed automatically.
@@ -23,67 +26,68 @@ After installing, you may want to look at the [examples](http://github.com/mongo
23
26
 
24
27
  ## Getting started
25
28
 
26
- #### Using the gem
29
+ Note that the output in the following has been updated to Ruby 1.9, so if you are using Ruby 1.8, you will see some minor differences. To follow this tutorial interactively, at the command line, run the Interactive Ruby Shell.
27
30
 
28
- All of the code here assumes that you have already executed the following Ruby code:
31
+ irb
29
32
 
30
- require 'rubygems' # not necessary for Ruby 1.9
31
- require 'mongo'
33
+ As you execute commands, irb will output the result using the `inspect` method. If you are editing and running a script for this tutorial, you can view output using the `puts` or `p` methods.
32
34
 
33
- #### Making a Connection
35
+ ### Using the gem
34
36
 
35
- An `Mongo::Connection` instance represents a connection to MongoDB. You use a Connection instance to obtain an Mongo:DB instance, which represents a named database. The database doesn't have to exist - if it doesn't, MongoDB will create it for you.
37
+ Use the `mongo` gem via the `require` kernel method.
36
38
 
37
- You can optionally specify the MongoDB server address and port when connecting. The following example shows three ways to connect to the database "mydb" on the local machine:
39
+ require 'rubygems' # not necessary for Ruby 1.9
40
+ require 'mongo'
38
41
 
39
- db = Mongo::Connection.new.db("mydb")
40
- db = Mongo::Connection.new("localhost").db("mydb")
41
- db = Mongo::Connection.new("localhost", 27017).db("mydb")
42
+ ### Making a Connection
42
43
 
43
- At this point, the `db` object will be a connection to a MongoDB server for the specified database. Each DB instance uses a separate socket connection to the server.
44
+ An `Mongo::Connection` instance represents a connection to MongoDB. You can optionally specify the MongoDB server address and port when connecting. The following example shows three ways to connect to the local machine:
44
45
 
45
- If you're trying to connect to a replica set, see [Replica Sets in Ruby](http://www.mongodb.org/display/DOCS/Replica+Sets+in+Ruby).
46
+ connection = Mongo::Connection.new # (optional host/port args)
47
+ connection = Mongo::Connection.new("localhost")
48
+ connection = Mongo::Connection.new("localhost", 27017)
46
49
 
47
- #### Listing All Databases
50
+ ### Listing All Databases
48
51
 
49
- connection = Mongo::Connection.new # (optional host/port args)
50
- connection.database_names.each { |name| puts name }
51
- connection.database_info.each { |info| puts info.inspect}
52
+ connection.database_names
53
+ connection.database_info.each { |info| puts info.inspect }
52
54
 
53
- #### Dropping a Database
54
- connection.drop_database('database_name')
55
+ The `database_info` method returns a hash mapping database names to the size of the database in bytes.
55
56
 
56
- MongoDB can be run in a secure mode where access to databases is controlled through name and password authentication. When run in this mode, any client application must provide a name and password before doing any operations. In the Ruby driver, you simply do the following with the connected mongo object:
57
+ ## Using a Database
57
58
 
58
- auth = db.authenticate(my_user_name, my_password)
59
+ You use a Connection instance to obtain an Mongo::DB instance, which represents a named database. The database doesn't have to exist - if it doesn't, MongoDB will create it for you. The following examples use the database "mydb":
59
60
 
60
- If the name and password are valid for the database, `auth` will be `true`. Otherwise, it will be `false`. You should look at the MongoDB log for further information if available.
61
+ db = connection.db("mydb")
62
+ db = Mongo::Connection.new.db("mydb")
61
63
 
62
- #### Getting a List Of Collections
64
+ At this point, the `db` object will be a connection to a MongoDB server for the specified database. Each DB instance uses a separate socket connection to the server.
63
65
 
64
- Each database has zero or more collections. You can retrieve a list of them from the db (and print out any that are there):
66
+ If you're trying to connect to a replica set, see [Replica Sets in Ruby](http://www.mongodb.org/display/DOCS/Replica+Sets+in+Ruby).
65
67
 
66
- db.collection_names.each { |name| puts name }
68
+ ### Authentication
67
69
 
68
- and assuming that there are two collections, name and address, in the database, you would see
70
+ MongoDB can be run in a secure mode where access to databases is controlled through name and password authentication. When run in this mode, any client application must provide a name and password before doing any operations. In the Ruby driver, you simply do the following with the connected mongo object:
69
71
 
70
- name
71
- address
72
+ auth = db.authenticate(my_user_name, my_password)
72
73
 
73
- as the output.
74
+ If the name and password are valid for the database, `auth` will be `true`. Otherwise, it will be `false`. You should look at the MongoDB log for further information if available.
74
75
 
75
- #### Getting a Collection
76
+ ## Using a Collection
76
77
 
77
78
  You can get a collection to use using the `collection` method:
79
+
78
80
  coll = db.collection("testCollection")
81
+
79
82
  This is aliased to the \[\] method:
83
+
80
84
  coll = db["testCollection"]
81
85
 
82
- Once you have this collection object, you can now do things like insert data, query for data, etc.
86
+ Once you have this collection object, you can now do create, read, update, and delete (CRUD) functions on persistent storage.
83
87
 
84
- #### Inserting a Document
88
+ ### Creating Documents with `insert`
85
89
 
86
- Once you have the collection object, you can insert documents into the collection. For example, lets make a little document that in JSON would be represented as
90
+ Once you have the collection object, you can create or `insert` documents into the collection. For example, lets make a little document that in JSON would be represented as
87
91
 
88
92
  {
89
93
  "name" : "MongoDB",
@@ -95,115 +99,158 @@ Once you have the collection object, you can insert documents into the collectio
95
99
  }
96
100
  }
97
101
 
98
- Notice that the above has an "inner" document embedded within it. To do this, we can use a Hash or the driver's OrderedHash (which preserves key order) to create the document (including the inner document), and then just simply insert it into the collection using the `insert()` method.
102
+ Notice that the above has an "inner" document embedded within it. To do this, we can use a Hash or the driver's OrderedHash (which preserves key order) to create the document (including the inner document), and then just simply insert it into the collection using the `insert` method.
99
103
 
100
- doc = {"name" => "MongoDB", "type" => "database", "count" => 1,
101
- "info" => {"x" => 203, "y" => '102'}}
102
- coll.insert(doc)
104
+ doc = {"name" => "MongoDB", "type" => "database", "count" => 1, "info" => {"x" => 203, "y" => '102'}}
105
+ id = coll.insert(doc)
103
106
 
104
- #### Updating a Document
107
+ We have saved the `id` for future use below. Now the collection has been created and you can list it.
105
108
 
106
- We can update the previous document using the `update` method. There are a couple ways to update a document. We can rewrite it:
109
+ #### Getting a List Of Collections
107
110
 
108
- doc["name"] = "MongoDB Ruby"
109
- coll.update({"_id" => doc["_id"]}, doc)
111
+ Each database has zero or more collections. You can retrieve a list of them from the db (and print out any that are there):
110
112
 
111
- Or we can use an atomic operator to change a single value:
113
+ db.collection_names
112
114
 
113
- coll.update({"_id" => doc["_id"]}, {"$set" => {"name" => "MongoDB Ruby"}})
115
+ You should see
114
116
 
115
- Read [more about updating documents|Updating].
117
+ \["testCollection", "system.indexes"\]
116
118
 
117
- #### Finding the First Document In a Collection using `find_one()`
119
+ #### Adding Multiple Documents
118
120
 
119
- To show that the document we inserted in the previous step is there, we can do a simple `find_one()` operation to get the first document in the collection. This method returns a single document (rather than the `Cursor` that the `find()` operation returns).
121
+ To demonstrate some more interesting queries, let's add multiple simple documents to the collection. These documents will have the following form:
120
122
 
121
- my_doc = coll.find_one()
122
- puts my_doc.inspect
123
+ {
124
+ "i" : value
125
+ }
123
126
 
124
- and you should see:
127
+ Here's how to insert them:
125
128
 
126
- {"_id"=>#<BSON::ObjectID:0x118576c ...>, "name"=>"MongoDB",
127
- "info"=>{"x"=>203, "y"=>102}, "type"=>"database", "count"=>1}
129
+ 100.times { |i| coll.insert("i" => i) }
128
130
 
129
- Note the `_id` element has been added automatically by MongoDB to your document.
131
+ Notice that we can insert documents of different "shapes" into the same collection. These records are in the same collection as the complex record we inserted above. This aspect is what we mean when we say that MongoDB is "schema-free".
130
132
 
131
- #### Adding Multiple Documents
133
+ ### Reading Documents with `find_one` and `find`
132
134
 
133
- To demonstrate some more interesting queries, let's add multiple simple documents to the collection. These documents will have the following form:
134
- {
135
- "i" : value
136
- }
135
+ #### Reading the First Document in a Collection using `find_one`
137
136
 
138
- Here's how to insert them:
137
+ To retrieve the document that we inserted, we can do a simple `find_one` method to get the first document in the collection. This method returns a single document directly.
139
138
 
140
- 100.times { |i| coll.insert("i" => i) }
139
+ coll.find_one
141
140
 
142
- Notice that we can insert documents of different "shapes" into the same collection. These records are in the same collection as the complex record we inserted above. This aspect is what we mean when we say that MongoDB is "schema-free".
141
+ and you should something like:
143
142
 
144
- #### Counting Documents in a Collection
143
+ {"_id"=>BSON::ObjectId('4f7b1ea6e4d30b35c9000001'), "name"=>"MongoDB", "type"=>"database", "count"=>1, "info"=>{"x"=>203, "y"=>"102"}}
145
144
 
146
- Now that we've inserted 101 documents (the 100 we did in the loop, plus the first one), we can check to see if we have them all using the `count()` method.
145
+ Note the `_id` element has been added automatically by MongoDB to your document.
147
146
 
148
- puts coll.count()
147
+ #### Reading All of the Documents with a Cursor using `find`
149
148
 
150
- and it should print `101`.
149
+ To get all the documents from the collection, we use the `find` method. `find` returns a `Cursor` object, which allows us to iterate over the set of documents that matches our query. The Ruby driver's Cursor implemented Enumerable, which allows us to use `Enumerable#each`, `Enumerable#map}, etc. For instance:
150
+
151
+ coll.find.each { |row| puts row.inspect }
151
152
 
152
- #### Using a Cursor to get all of the Documents
153
+ and that should print all 101 documents in the collection. You can take advantage of `Enumerable#to_a`.
153
154
 
154
- To get all the documents from the collection, we use the `find()` method. `find()` returns a `Cursor` object, which allows us to iterate over the set of documents that matches our query. The Ruby driver's Cursor implemented Enumerable, which allows us to use `Enumerable#each`, `Enumerable#map}, etc. For instance:
155
+ puts coll.find.to_a
155
156
 
156
- coll.find().each { |row| puts row.inspect }
157
+ Important note - using `to_a` pulls all of the full result set into memory and is inefficient if you can process by each individual document. To process with more memory efficiency, use the `each` method with a code block for the cursor.
157
158
 
158
- and that should print all 101 documents in the collection.
159
+ #### Specific Queries
159
160
 
160
- #### Getting a Single Document with a Query
161
+ We can create a _query_ hash to pass to the `find` method to get a subset of the documents in our collection. To check that our update worked, find the document by id:
161
162
 
162
- We can create a _query_ hash to pass to the `find()` method to get a subset of the documents in our collection. For example, if we wanted to find the document for which the value of the "i" field is 71, we would do the following ;
163
+ coll.find("_id" => id).to_a
163
164
 
164
- coll.find("i" => 71).each { |row| puts row.inspect }
165
+ If we wanted to find the document for which the value of the "i" field is 71, we would do the following:
166
+
167
+ coll.find("i" => 71).to_a
165
168
 
166
169
  and it should just print just one document:
167
170
 
168
- {"_id"=>#<BSON::ObjectID:0x117de90 ...>, "i"=>71}
171
+ {"_id"=>BSON::ObjectId('4f7b20b4e4d30b35c9000049'), "i"=>71}
172
+
173
+ #### Counting Documents in a Collection
174
+
175
+ Now that we've inserted 101 documents (the 100 we did in the loop, plus the first one), we can check to see if we have them all using the `count` method.
176
+
177
+ coll.count
178
+
179
+ and it should print `101`.
169
180
 
170
181
  #### Getting a Set of Documents With a Query
171
182
 
172
183
  We can use the query to get a set of documents from our collection. For example, if we wanted to get all documents where "i" > 50, we could write:
173
184
 
174
- coll.find("i" => {"$gt" => 50}).each { |row| puts row }
185
+ puts coll.find("i" => {"$gt" => 50}).to_a
175
186
 
176
187
  which should print the documents where i > 50. We could also get a range, say 20 < i <= 30:
177
188
 
178
- coll.find("i" => {"$gt" => 20, "$lte" => 30}).each { |row| puts row }
189
+ puts coll.find("i" => {"$gt" => 20, "$lte" => 30}).to_a
179
190
 
180
- #### Selecting a subset of fields for a query
191
+ #### Selecting a Subset of Fields for a Query
181
192
 
182
- Use the `:fields` option. If you just want fields "a" and "b":
193
+ Use the `:fields` option to specify fields to return.
183
194
 
184
- coll.find("i" => {"$gt" => 50}, :fields => ["a", "b"]).each { |row| puts row }
195
+ puts coll.find("_id" => id, :fields => ["name", "type"]).to_a
185
196
 
186
197
  #### Querying with Regular Expressions
187
198
 
188
199
  Regular expressions can be used to query MongoDB. To find all names that begin with 'a':
189
200
 
190
- coll.find({"name" => /^a/})
201
+ puts coll.find({"name" => /^M/}).to_a
191
202
 
192
203
  You can also construct a regular expression dynamically. To match a given search string:
193
204
 
205
+ params = {'search' => 'DB'}
194
206
  search_string = params['search']
195
207
 
196
208
  # Constructor syntax
197
- coll.find({"name" => Regexp.new(search_string)})
209
+ puts coll.find({"name" => Regexp.new(search_string)}).to_a
198
210
 
199
211
  # Literal syntax
200
- coll.find({"name" => /#{search_string}/})
212
+ puts coll.find({"name" => /#{search_string}/}).to_a
201
213
 
202
214
  Although MongoDB isn't vulnerable to anything like SQL-injection, it may be worth checking the search string for anything malicious.
203
215
 
216
+ ### Updating Documents with `update`
217
+
218
+ We can update the previous document using the `update` method. There are a couple ways to update a document. We can rewrite it:
219
+
220
+ doc["name"] = "MongoDB Ruby"
221
+ coll.update({"_id" => id}, doc)
222
+
223
+ Or we can use an atomic operator to change a single value:
224
+
225
+ coll.update({"_id" => id}, {"$set" => {"name" => "MongoDB Ruby"}})
226
+
227
+ Verify the update.
228
+
229
+ puts coll.find("_id" => id).to_a
230
+
231
+ Read [more about updating documents|Updating].
232
+
233
+ ### Deleting Documents with `remove`
234
+
235
+ Use the `remove` method to delete documents.
236
+
237
+ coll.count
238
+ coll.remove("i" => 71)
239
+ coll.count
240
+ puts coll.find("i" => 71).to_a
241
+
242
+ The above shows that the count has been reduced and that the document can no longer be found.
243
+
244
+ Without arguments, the `remove` method deletes all documents.
245
+
246
+ coll.remove
247
+ coll.count
248
+
249
+ Please program carefully.
250
+
204
251
  ## Indexing
205
252
 
206
- #### Creating An Index
253
+ ### Creating An Index
207
254
 
208
255
  MongoDB supports indexes, and they are very easy to add on a collection. To create an index, you specify an index name and an array of field names to be indexed, or a single field name. The following creates an ascending index on the "i" field:
209
256
 
@@ -215,7 +262,21 @@ To specify complex indexes or a descending index you need to use a slightly more
215
262
  # Explicit "ascending"
216
263
  coll.create_index([["i", Mongo::ASCENDING]])
217
264
 
218
- #### Creating and querying on a geospatial index
265
+ Use the `explain` method on the cursor to show how MongoDB will run the query.
266
+
267
+ coll.find("_id" => id).explain
268
+ coll.find("i" => 71).explain
269
+ coll.find("type" => "database").explain
270
+
271
+ The above shows that the query by `_id` and `i` will use faster indexed BtreeCursor, while the query by `type` will use a slower BasicCursor.
272
+
273
+ ### Getting a List of Indexes on a Collection
274
+
275
+ You can get a list of the indexes on a collection.
276
+
277
+ coll.index_information
278
+
279
+ ### Creating and Querying on a Geospatial Index
219
280
 
220
281
  First, create the index on a field containing long-lat values:
221
282
 
@@ -224,12 +285,48 @@ First, create the index on a field containing long-lat values:
224
285
  Then get a list of the twenty locations nearest to the point 50, 50:
225
286
 
226
287
  people.find({"loc" => {"$near" => [50, 50]}}, {:limit => 20}).each do |p|
227
- puts p.inspect
288
+ puts p.inspect
228
289
  end
229
290
 
230
- #### Getting a List of Indexes on a Collection
291
+ ## Dropping
292
+
293
+ ### Drop an Index
294
+
295
+ To drop a secondary index, use the `drop_index` method on the collection.
296
+
297
+ coll.drop_index("i_1")
298
+ coll.index_information
299
+
300
+ The dropped index is no longer listed.
301
+
302
+ ### Drop All Indexes
303
+
304
+ To drop all secondary indexes, use the `drop_indexes` method on the collection.
305
+
306
+ coll.drop_indexes
307
+ coll.index_information
308
+
309
+ Only the primary index "_id_" is listed.
310
+
311
+ ### Drop a Collection
312
+
313
+ To drop a collection, use the `drop` method on the collection.
314
+
315
+ coll.drop
316
+ db.collection_names
317
+
318
+ The dropped collection is no longer listed. The `drop_collection` method can be used on the database as an alternative.
319
+
320
+ db.drop_collection("testCollection")
321
+
322
+ ### Drop a Database
323
+
324
+ To drop a database, use the `drop_database` method on the connection.
325
+
326
+ connection.drop_database("mydb")
327
+ connection.database_names
231
328
 
232
- You can get a list of the indexes on a collection using `coll.index_information()`.
329
+ The dropped database is no longer listed.
233
330
 
234
331
  ## Database Administration
235
332