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.
- data/README.rdoc +37 -28
- data/Rakefile +19 -0
- data/bin/objectid_benchmark.rb +23 -0
- data/examples/admin.rb +7 -6
- data/examples/capped.rb +3 -4
- data/examples/cursor.rb +4 -3
- data/examples/gridfs.rb +3 -2
- data/examples/index_test.rb +10 -9
- data/examples/info.rb +3 -2
- data/examples/queries.rb +3 -2
- data/examples/simple.rb +3 -2
- data/examples/strict.rb +2 -1
- data/examples/types.rb +4 -3
- data/lib/mongo.rb +29 -12
- data/lib/mongo/admin.rb +17 -2
- data/lib/mongo/collection.rb +230 -169
- data/lib/mongo/connection.rb +136 -91
- data/lib/mongo/cursor.rb +68 -40
- data/lib/mongo/db.rb +247 -123
- data/lib/mongo/{errors.rb → exceptions.rb} +6 -5
- data/lib/mongo/gridfs.rb +6 -0
- data/lib/mongo/gridfs/grid_store.rb +142 -94
- data/lib/mongo/types/binary.rb +11 -1
- data/lib/mongo/types/code.rb +6 -1
- data/lib/mongo/types/dbref.rb +7 -2
- data/lib/mongo/types/min_max_keys.rb +58 -0
- data/lib/mongo/types/objectid.rb +76 -20
- data/lib/mongo/types/regexp_of_holding.rb +5 -0
- data/lib/mongo/util/bson_ruby.rb +36 -2
- data/lib/mongo/util/byte_buffer.rb +18 -2
- data/lib/mongo/util/conversions.rb +6 -5
- data/lib/mongo/util/ordered_hash.rb +3 -1
- data/lib/mongo/util/support.rb +3 -0
- data/lib/mongo/util/xml_to_ruby.rb +7 -0
- data/test/test_bson.rb +48 -0
- data/test/test_collection.rb +13 -0
- data/test/test_connection.rb +35 -0
- data/test/test_conversions.rb +1 -1
- data/test/test_cursor.rb +37 -5
- data/test/test_db.rb +51 -2
- data/test/test_db_api.rb +4 -7
- data/test/test_grid_store.rb +10 -0
- data/test/test_objectid.rb +16 -2
- data/test/test_ordered_hash.rb +14 -0
- data/test/threading/test_threading_large_pool.rb +4 -4
- data/test/unit/db_test.rb +43 -0
- metadata +5 -7
- data/examples/benchmarks.rb +0 -42
- data/examples/blog.rb +0 -76
- data/lib/mongo/constants.rb +0 -15
- data/test/mongo-qa/_common.rb +0 -8
data/lib/mongo/connection.rb
CHANGED
@@ -20,11 +20,10 @@ require 'thread'
|
|
20
20
|
|
21
21
|
module Mongo
|
22
22
|
|
23
|
-
#
|
23
|
+
# Instantiates and manages connections to MongoDB.
|
24
24
|
class Connection
|
25
25
|
|
26
|
-
#
|
27
|
-
# a ConnectionError is raised.
|
26
|
+
# Abort connections if a ConnectionError is raised.
|
28
27
|
Thread.abort_on_exception = true
|
29
28
|
|
30
29
|
DEFAULT_PORT = 27017
|
@@ -33,70 +32,59 @@ module Mongo
|
|
33
32
|
|
34
33
|
attr_reader :logger, :size, :host, :port, :nodes, :sockets, :checked_out
|
35
34
|
|
36
|
-
def slave_ok?
|
37
|
-
@slave_ok
|
38
|
-
end
|
39
|
-
|
40
35
|
# Counter for generating unique request ids.
|
41
36
|
@@current_request_id = 0
|
42
37
|
|
43
|
-
#
|
38
|
+
# Create a connection to MongoDB. Specify either one or a pair of servers,
|
44
39
|
# along with a maximum connection pool size and timeout.
|
45
40
|
#
|
46
|
-
# == Connecting
|
47
41
|
# If connecting to just one server, you may specify whether connection to slave is permitted.
|
42
|
+
# In all cases, the default host is "localhost" and the default port is 27017.
|
48
43
|
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
# When specifying a pair, pair_or_host, is a hash with two keys: :left and :right. Each key maps to either
|
44
|
+
# When specifying a pair, +pair_or_host+, is a hash with two keys: :left and :right. Each key maps to either
|
52
45
|
# * a server name, in which case port is 27017,
|
53
46
|
# * a port number, in which case the server is "localhost", or
|
54
47
|
# * an array containing [server_name, port_number]
|
55
48
|
#
|
56
|
-
# === Options
|
57
|
-
#
|
58
|
-
# :slave_ok :: Defaults to +false+. Must be set to +true+ when connecting
|
59
|
-
# to a single, slave node.
|
60
|
-
#
|
61
|
-
# :logger :: Optional Logger instance to which driver usage information
|
62
|
-
# will be logged.
|
63
|
-
#
|
64
|
-
# :auto_reconnect :: DEPRECATED. See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
|
65
|
-
#
|
66
|
-
# :pool_size :: The maximum number of socket connections that can be opened
|
67
|
-
# that can be opened to the database.
|
68
|
-
#
|
69
|
-
# :timeout :: When all of the connections to the pool are checked out,
|
70
|
-
# this is the number of seconds to wait for a new connection
|
71
|
-
# to be released before throwing an exception.
|
72
|
-
#
|
73
49
|
# Note that there are a few issues when using connection pooling with Ruby 1.9 on Windows. These
|
74
50
|
# should be resolved in the next release.
|
75
51
|
#
|
76
|
-
#
|
52
|
+
# @param [String, Hash] pair_or_host See explanation above.
|
53
|
+
# @param [Integer] port specify a port number here if only one host is being specified. Leave nil if
|
54
|
+
# specifying a pair of servers in +pair_or_host+.
|
77
55
|
#
|
78
|
-
#
|
79
|
-
#
|
56
|
+
# @option options [Boolean] :slave_ok (false) Must be set to +true+ when connecting
|
57
|
+
# to a single, slave node.
|
58
|
+
# @option options [Logger, #debug] :logger (nil) Logger instance to receive driver operation log.
|
59
|
+
# @option options [Boolean] :auto_reconnect DEPRECATED. See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
|
60
|
+
# @option options [Integer] :pool_size (1) The maximum number of socket connections that can be opened to the database.
|
61
|
+
# @option options [Float] :timeout (5.0) When all of the connections to the pool are checked out,
|
62
|
+
# this is the number of seconds to wait for a new connection to be released before throwing an exception.
|
80
63
|
#
|
81
|
-
# # localhost, 27017
|
82
|
-
# Connection.new("localhost")
|
83
64
|
#
|
84
|
-
#
|
85
|
-
#
|
65
|
+
# @example localhost, 27017
|
66
|
+
# Connection.new
|
86
67
|
#
|
87
|
-
#
|
88
|
-
#
|
68
|
+
# @example localhost, 27017
|
69
|
+
# Connection.new("localhost")
|
89
70
|
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
71
|
+
# @example localhost, 3000, max 5 connections, with max 5 seconds of wait time.
|
72
|
+
# Connection.new("localhost", 3000, :pool_size => 5, :timeout => 5)
|
73
|
+
#
|
74
|
+
# @example localhost, 3000, where this node may be a slave
|
75
|
+
# Connection.new("localhost", 3000, :slave_ok => true)
|
76
|
+
#
|
77
|
+
# @example A pair of servers. The driver will always talk to master.
|
78
|
+
# # On connection errors, Mongo::ConnectionFailure will be raised.
|
79
|
+
# Connection.new({:left => ["db1.example.com", 27017],
|
94
80
|
# :right => ["db2.example.com", 27017]})
|
95
81
|
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
82
|
+
# @example A pair of servers with connection pooling enabled. Note the nil param placeholder for port.
|
83
|
+
# Connection.new({:left => ["db1.example.com", 27017],
|
84
|
+
# :right => ["db2.example.com", 27017]}, nil,
|
85
|
+
# :pool_size => 20, :timeout => 5)
|
86
|
+
#
|
87
|
+
# @see http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby Replica pairs in Ruby
|
100
88
|
def initialize(pair_or_host=nil, port=nil, options={})
|
101
89
|
@nodes = format_pair(pair_or_host, port)
|
102
90
|
|
@@ -124,7 +112,7 @@ module Mongo
|
|
124
112
|
warn(":auto_reconnect is deprecated. see http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby")
|
125
113
|
end
|
126
114
|
|
127
|
-
#
|
115
|
+
# slave_ok can be true only if one node is specified
|
128
116
|
@slave_ok = options[:slave_ok] && @nodes.length == 1
|
129
117
|
@logger = options[:logger] || nil
|
130
118
|
@options = options
|
@@ -133,8 +121,10 @@ module Mongo
|
|
133
121
|
connect_to_master if should_connect
|
134
122
|
end
|
135
123
|
|
136
|
-
#
|
137
|
-
# disk.
|
124
|
+
# Return a hash with all database names
|
125
|
+
# and their respective sizes on disk.
|
126
|
+
#
|
127
|
+
# @return [Hash]
|
138
128
|
def database_info
|
139
129
|
doc = self['admin'].command(:listDatabases => 1)
|
140
130
|
returning({}) do |info|
|
@@ -142,39 +132,57 @@ module Mongo
|
|
142
132
|
end
|
143
133
|
end
|
144
134
|
|
145
|
-
#
|
135
|
+
# Return an array of database names.
|
136
|
+
#
|
137
|
+
# @return [Array]
|
146
138
|
def database_names
|
147
139
|
database_info.keys
|
148
140
|
end
|
149
141
|
|
150
|
-
#
|
151
|
-
# See DB#new for
|
142
|
+
# Return a database with the given name.
|
143
|
+
# See DB#new for valid options hash parameters.
|
144
|
+
#
|
145
|
+
# @param [String] db_name a valid database name.
|
146
|
+
#
|
147
|
+
# @return [Mongo::DB]
|
152
148
|
def db(db_name, options={})
|
153
149
|
DB.new(db_name, self, options.merge(:logger => @logger))
|
154
150
|
end
|
155
151
|
|
156
|
-
#
|
152
|
+
# Shortcut for returning a database. Use DB#db to accept options.
|
153
|
+
#
|
154
|
+
# @param [String] db_name a valid database name.
|
155
|
+
#
|
156
|
+
# @return [Mongo::DB]
|
157
157
|
def [](db_name)
|
158
158
|
DB.new(db_name, self, :logger => @logger)
|
159
159
|
end
|
160
160
|
|
161
|
-
#
|
161
|
+
# Drop a database.
|
162
|
+
#
|
163
|
+
# @param [String] name name of an existing database.
|
162
164
|
def drop_database(name)
|
163
165
|
self[name].command(:dropDatabase => 1)
|
164
166
|
end
|
165
167
|
|
166
|
-
#
|
168
|
+
# Copy the database +from+ on the local server to +to+ on the specified +host+.
|
167
169
|
# +host+ defaults to 'localhost' if no value is provided.
|
168
|
-
|
170
|
+
#
|
171
|
+
# @param [String] from name of the database to copy from.
|
172
|
+
# @param [String] to name of the database to copy to.
|
173
|
+
# @param [String] from_host host of the 'from' database.
|
174
|
+
def copy_database(from, to, from_host="localhost")
|
169
175
|
oh = OrderedHash.new
|
170
176
|
oh[:copydb] = 1
|
171
|
-
oh[:fromhost] =
|
177
|
+
oh[:fromhost] = from_host
|
172
178
|
oh[:fromdb] = from
|
173
179
|
oh[:todb] = to
|
174
180
|
self["admin"].command(oh)
|
175
181
|
end
|
176
182
|
|
177
|
-
#
|
183
|
+
# Increment and return the next available request id.
|
184
|
+
#
|
185
|
+
# return [Integer]
|
178
186
|
def get_request_id
|
179
187
|
request_id = ''
|
180
188
|
@id_lock.synchronize do
|
@@ -183,51 +191,75 @@ module Mongo
|
|
183
191
|
request_id
|
184
192
|
end
|
185
193
|
|
186
|
-
#
|
194
|
+
# Get the build information for the current connection.
|
195
|
+
#
|
196
|
+
# @return [Hash]
|
187
197
|
def server_info
|
188
198
|
db("admin").command({:buildinfo => 1}, {:admin => true, :check_response => true})
|
189
199
|
end
|
190
200
|
|
191
|
-
#
|
192
|
-
#
|
201
|
+
# Get the build version of the current server.
|
202
|
+
#
|
203
|
+
# @return [Mongo::ServerVersion]
|
204
|
+
# object allowing easy comparability of version.
|
193
205
|
def server_version
|
194
206
|
ServerVersion.new(server_info["version"])
|
195
207
|
end
|
196
208
|
|
209
|
+
# Is it okay to connect to a slave?
|
210
|
+
#
|
211
|
+
# @return [Boolean]
|
212
|
+
def slave_ok?
|
213
|
+
@slave_ok
|
214
|
+
end
|
215
|
+
|
197
216
|
|
198
217
|
## Connections and pooling ##
|
199
218
|
|
200
|
-
#
|
219
|
+
# Send a message to MongoDB, adding the necessary headers.
|
201
220
|
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
221
|
+
# @param [Integer] operation a MongoDB opcode.
|
222
|
+
# @param [ByteBuffer] message a message to send to the database.
|
223
|
+
# @param [String] log_message text version of +message+ for logging.
|
224
|
+
#
|
225
|
+
# @return [True]
|
205
226
|
def send_message(operation, message, log_message=nil)
|
206
227
|
@logger.debug(" MONGODB #{log_message || message}") if @logger
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
228
|
+
begin
|
229
|
+
packed_message = add_message_headers(operation, message).to_s
|
230
|
+
socket = checkout
|
231
|
+
send_message_on_socket(packed_message, socket)
|
232
|
+
ensure
|
233
|
+
checkin(socket)
|
234
|
+
end
|
211
235
|
end
|
212
236
|
|
213
237
|
# Sends a message to the database, waits for a response, and raises
|
214
238
|
# an exception if the operation has failed.
|
215
239
|
#
|
216
|
-
#
|
217
|
-
#
|
218
|
-
#
|
240
|
+
# @param [Integer] operation a MongoDB opcode.
|
241
|
+
# @param [ByteBuffer] message a message to send to the database.
|
242
|
+
# @param [String] db_name the name of the database. used on call to get_last_error.
|
243
|
+
# @param [String] log_message text version of +message+ for logging.
|
244
|
+
#
|
245
|
+
# @return [Array]
|
246
|
+
# An array whose indexes include [0] documents returned, [1] number of document received,
|
247
|
+
# and [3] a cursor_id.
|
219
248
|
def send_message_with_safe_check(operation, message, db_name, log_message=nil)
|
220
249
|
message_with_headers = add_message_headers(operation, message)
|
221
250
|
message_with_check = last_error_message(db_name)
|
222
251
|
@logger.debug(" MONGODB #{log_message || message}") if @logger
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
252
|
+
begin
|
253
|
+
sock = checkout
|
254
|
+
packed_message = message_with_headers.append!(message_with_check).to_s
|
255
|
+
docs = num_received = cursor_id = ''
|
256
|
+
@safe_mutex.synchronize do
|
257
|
+
send_message_on_socket(packed_message, sock)
|
258
|
+
docs, num_received, cursor_id = receive(sock)
|
259
|
+
end
|
260
|
+
ensure
|
261
|
+
checkin(sock)
|
229
262
|
end
|
230
|
-
checkin(sock)
|
231
263
|
if num_received == 1 && error = docs[0]['err']
|
232
264
|
raise Mongo::OperationFailure, error
|
233
265
|
end
|
@@ -236,25 +268,35 @@ module Mongo
|
|
236
268
|
|
237
269
|
# Sends a message to the database and waits for the response.
|
238
270
|
#
|
239
|
-
#
|
240
|
-
#
|
241
|
-
#
|
271
|
+
# @param [Integer] operation a MongoDB opcode.
|
272
|
+
# @param [ByteBuffer] message a message to send to the database.
|
273
|
+
# @param [String] log_message text version of +message+ for logging.
|
274
|
+
# @param [Socket] socket a socket to use in lieu of checking out a new one.
|
275
|
+
#
|
276
|
+
# @return [Array]
|
277
|
+
# An array whose indexes include [0] documents returned, [1] number of document received,
|
278
|
+
# and [3] a cursor_id.
|
242
279
|
def receive_message(operation, message, log_message=nil, socket=nil)
|
243
280
|
packed_message = add_message_headers(operation, message).to_s
|
244
281
|
@logger.debug(" MONGODB #{log_message || message}") if @logger
|
245
|
-
|
282
|
+
begin
|
283
|
+
sock = socket || checkout
|
246
284
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
285
|
+
result = ''
|
286
|
+
@safe_mutex.synchronize do
|
287
|
+
send_message_on_socket(packed_message, sock)
|
288
|
+
result = receive(sock)
|
289
|
+
end
|
290
|
+
ensure
|
291
|
+
checkin(sock)
|
251
292
|
end
|
252
|
-
checkin(sock)
|
253
293
|
result
|
254
294
|
end
|
255
295
|
|
256
|
-
#
|
257
|
-
# If successful, sets
|
296
|
+
# Create a new socket and attempt to connect to master.
|
297
|
+
# If successful, sets host and port to master and returns the socket.
|
298
|
+
#
|
299
|
+
# @raise [ConnectionFailure] if unable to connect to any host or port.
|
258
300
|
def connect_to_master
|
259
301
|
close
|
260
302
|
@host = @port = nil
|
@@ -286,7 +328,7 @@ module Mongo
|
|
286
328
|
end
|
287
329
|
|
288
330
|
# Are we connected to MongoDB? This is determined by checking whether
|
289
|
-
#
|
331
|
+
# host and port have values, since they're set to nil on calls to #close.
|
290
332
|
def connected?
|
291
333
|
@host && @port
|
292
334
|
end
|
@@ -361,6 +403,9 @@ module Mongo
|
|
361
403
|
return socket if socket
|
362
404
|
|
363
405
|
# Otherwise, wait
|
406
|
+
if @logger
|
407
|
+
@logger.warn "Waiting for available connection; #{@checked_out.size} of #{@size} connections checked out."
|
408
|
+
end
|
364
409
|
@queue.wait(@connection_mutex)
|
365
410
|
end
|
366
411
|
end
|
data/lib/mongo/cursor.rb
CHANGED
@@ -25,7 +25,10 @@ module Mongo
|
|
25
25
|
|
26
26
|
# Create a new cursor.
|
27
27
|
#
|
28
|
-
#
|
28
|
+
# Note: cursors are created when executing queries using [Collection#find] and other
|
29
|
+
# similar methods. Application developers shouldn't have to create cursors manually.
|
30
|
+
#
|
31
|
+
# @return [Cursor]
|
29
32
|
def initialize(collection, options={})
|
30
33
|
@db = collection.db
|
31
34
|
@collection = collection
|
@@ -49,7 +52,9 @@ module Mongo
|
|
49
52
|
@query_run = false
|
50
53
|
end
|
51
54
|
|
52
|
-
#
|
55
|
+
# Get the next document specified the cursor options.
|
56
|
+
#
|
57
|
+
# @return [Hash, Nil] the next document or Nil if no documents remain.
|
53
58
|
def next_document
|
54
59
|
refill_via_get_more if num_remaining == 0
|
55
60
|
doc = @cache.shift
|
@@ -71,6 +76,7 @@ module Mongo
|
|
71
76
|
doc
|
72
77
|
end
|
73
78
|
|
79
|
+
# @deprecated use Cursor#next_document instead.
|
74
80
|
def next_object
|
75
81
|
warn "Cursor#next_object is deprecated; please use Cursor#next_document instead."
|
76
82
|
next_document
|
@@ -78,9 +84,10 @@ module Mongo
|
|
78
84
|
|
79
85
|
# Get the size of the result set for this query.
|
80
86
|
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
87
|
+
# @return [Integer] the number of objects in the result set for this query. Does
|
88
|
+
# not take limit and skip into account.
|
89
|
+
#
|
90
|
+
# @raise [OperationFailure] on a database error.
|
84
91
|
def count
|
85
92
|
command = OrderedHash["count", @collection.name,
|
86
93
|
"query", @selector,
|
@@ -93,15 +100,16 @@ module Mongo
|
|
93
100
|
|
94
101
|
# Sort this cursor's results.
|
95
102
|
#
|
96
|
-
# Takes either a single key and a direction, or an array of [key,
|
97
|
-
# direction] pairs. Directions should be specified as Mongo::ASCENDING / Mongo::DESCENDING
|
98
|
-
# (or :ascending / :descending, :asc / :desc).
|
99
|
-
#
|
100
|
-
# Raises InvalidOperation if this cursor has already been used. Raises
|
101
|
-
# InvalidSortValueError if the specified order is invalid.
|
102
|
-
#
|
103
103
|
# This method overrides any sort order specified in the Collection#find
|
104
104
|
# method, and only the last sort applied has an effect.
|
105
|
+
#
|
106
|
+
# @param [Symbol, Array] key_or_list either 1) a key to sort by or 2)
|
107
|
+
# an array of [key, direction] pairs to sort by. Direction should
|
108
|
+
# be specified as Mongo::ASCENDING (or :ascending / :asc) or Mongo::DESCENDING (or :descending / :desc)
|
109
|
+
#
|
110
|
+
# @raise [InvalidOperation] if this cursor has already been used.
|
111
|
+
#
|
112
|
+
# @raise [InvalidSortValueError] if the specified order is invalid.
|
105
113
|
def sort(key_or_list, direction=nil)
|
106
114
|
check_modifiable
|
107
115
|
|
@@ -115,13 +123,14 @@ module Mongo
|
|
115
123
|
self
|
116
124
|
end
|
117
125
|
|
118
|
-
#
|
119
|
-
# Returns the current number_to_return if no parameter is given.
|
120
|
-
#
|
121
|
-
# Raises InvalidOperation if this cursor has already been used.
|
126
|
+
# Limit the number of results to be returned by this cursor.
|
122
127
|
#
|
123
128
|
# This method overrides any limit specified in the Collection#find method,
|
124
129
|
# and only the last limit applied has an effect.
|
130
|
+
#
|
131
|
+
# @return [Integer] the current number_to_return if no parameter is given.
|
132
|
+
#
|
133
|
+
# @raise [InvalidOperation] if this cursor has already been used.
|
125
134
|
def limit(number_to_return=nil)
|
126
135
|
return @limit unless number_to_return
|
127
136
|
check_modifiable
|
@@ -134,10 +143,12 @@ module Mongo
|
|
134
143
|
# Skips the first +number_to_skip+ results of this cursor.
|
135
144
|
# Returns the current number_to_skip if no parameter is given.
|
136
145
|
#
|
137
|
-
# Raises InvalidOperation if this cursor has already been used.
|
138
|
-
#
|
139
146
|
# This method overrides any skip specified in the Collection#find method,
|
140
147
|
# and only the last skip applied has an effect.
|
148
|
+
#
|
149
|
+
# @return [Integer]
|
150
|
+
#
|
151
|
+
# @raise [InvalidOperation] if this cursor has already been used.
|
141
152
|
def skip(number_to_skip=nil)
|
142
153
|
return @skip unless number_to_skip
|
143
154
|
check_modifiable
|
@@ -151,6 +162,13 @@ module Mongo
|
|
151
162
|
# block.
|
152
163
|
#
|
153
164
|
# Iterating over an entire cursor will close it.
|
165
|
+
#
|
166
|
+
# @yield passes each document to a block for processing.
|
167
|
+
#
|
168
|
+
# @example if 'comments' represents a collection of comments:
|
169
|
+
# comments.find.each do |doc|
|
170
|
+
# puts doc['user']
|
171
|
+
# end
|
154
172
|
def each
|
155
173
|
num_returned = 0
|
156
174
|
while more? && (@limit <= 0 || num_returned < @limit)
|
@@ -159,13 +177,15 @@ module Mongo
|
|
159
177
|
end
|
160
178
|
end
|
161
179
|
|
162
|
-
#
|
180
|
+
# Receive all the documents from this cursor as an array of hashes.
|
163
181
|
#
|
164
|
-
#
|
165
|
-
#
|
182
|
+
# Note: use of this method is discouraged - in most cases, it's much more
|
183
|
+
# efficient to retrieve documents as you need them by iterating over the cursor.
|
166
184
|
#
|
167
|
-
#
|
168
|
-
#
|
185
|
+
# @return [Array] an array of documents.
|
186
|
+
#
|
187
|
+
# @raise [InvalidOperation] if this cursor has already been used or if
|
188
|
+
# this method has already been called on the cursor.
|
169
189
|
def to_a
|
170
190
|
raise InvalidOperation, "can't call Cursor#to_a on a used cursor" if @query_run
|
171
191
|
rows = []
|
@@ -177,7 +197,9 @@ module Mongo
|
|
177
197
|
rows
|
178
198
|
end
|
179
199
|
|
180
|
-
#
|
200
|
+
# Get the explain plan for this cursor.
|
201
|
+
#
|
202
|
+
# @return [Hash] a document containing the explain plan for this cursor.
|
181
203
|
def explain
|
182
204
|
c = Cursor.new(@collection, query_options_hash.merge(:limit => -@limit.abs, :explain => true))
|
183
205
|
explanation = c.next_document
|
@@ -186,19 +208,19 @@ module Mongo
|
|
186
208
|
explanation
|
187
209
|
end
|
188
210
|
|
189
|
-
#
|
211
|
+
# Close the cursor.
|
190
212
|
#
|
191
213
|
# Note: if a cursor is read until exhausted (read until Mongo::Constants::OP_QUERY or
|
192
214
|
# Mongo::Constants::OP_GETMORE returns zero for the cursor id), there is no need to
|
193
|
-
# close it
|
215
|
+
# close it manually.
|
216
|
+
#
|
217
|
+
# Note also: Collection#find takes an optional block argument which can be used to
|
218
|
+
# ensure that your cursors get closed.
|
194
219
|
#
|
195
|
-
#
|
196
|
-
# ensure that your cursors get closed. See the documentation for
|
197
|
-
# Collection#find for details.
|
220
|
+
# @return [True]
|
198
221
|
def close
|
199
222
|
if @cursor_id
|
200
|
-
message = ByteBuffer.new
|
201
|
-
message.put_int(0)
|
223
|
+
message = ByteBuffer.new([0, 0, 0, 0])
|
202
224
|
message.put_int(1)
|
203
225
|
message.put_long(@cursor_id)
|
204
226
|
@connection.send_message(Mongo::Constants::OP_KILL_CURSORS, message, "cursor.close()")
|
@@ -207,18 +229,26 @@ module Mongo
|
|
207
229
|
@closed = true
|
208
230
|
end
|
209
231
|
|
210
|
-
#
|
232
|
+
# Is this cursor closed?
|
233
|
+
#
|
234
|
+
# @return [Boolean]
|
211
235
|
def closed?; @closed; end
|
212
236
|
|
213
237
|
# Returns an integer indicating which query options have been selected.
|
214
|
-
#
|
238
|
+
#
|
239
|
+
# @return [Integer]
|
240
|
+
#
|
241
|
+
# @see http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
|
242
|
+
# The MongoDB wire protocol.
|
215
243
|
def query_opts
|
216
244
|
timeout = @timeout ? 0 : Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT
|
217
245
|
slave_ok = @connection.slave_ok? ? Mongo::Constants::OP_QUERY_SLAVE_OK : 0
|
218
246
|
slave_ok + timeout
|
219
247
|
end
|
220
248
|
|
221
|
-
#
|
249
|
+
# Get the query options for this Cursor.
|
250
|
+
#
|
251
|
+
# @return [Hash]
|
222
252
|
def query_options_hash
|
223
253
|
{ :selector => @selector,
|
224
254
|
:fields => @fields,
|
@@ -233,7 +263,7 @@ module Mongo
|
|
233
263
|
|
234
264
|
private
|
235
265
|
|
236
|
-
#
|
266
|
+
# Convert the +:fields+ parameter from a single field name or an array
|
237
267
|
# of fields names to a hash, with the field names for keys and '1' for each
|
238
268
|
# value.
|
239
269
|
def convert_fields_for_query(fields)
|
@@ -284,9 +314,7 @@ module Mongo
|
|
284
314
|
|
285
315
|
def refill_via_get_more
|
286
316
|
return if send_initial_query || @cursor_id.zero?
|
287
|
-
message = ByteBuffer.new
|
288
|
-
# Reserved.
|
289
|
-
message.put_int(0)
|
317
|
+
message = ByteBuffer.new([0, 0, 0, 0])
|
290
318
|
|
291
319
|
# DB name.
|
292
320
|
db_name = @admin ? 'admin' : @db.name
|
@@ -328,8 +356,8 @@ module Mongo
|
|
328
356
|
if query_contains_special_fields?
|
329
357
|
selector = selector_with_special_query_fields
|
330
358
|
end
|
331
|
-
message.put_array(BSON.serialize(selector, false).
|
332
|
-
message.put_array(BSON.serialize(@fields, false).
|
359
|
+
message.put_array(BSON.serialize(selector, false).to_a)
|
360
|
+
message.put_array(BSON.serialize(@fields, false).to_a) if @fields
|
333
361
|
message
|
334
362
|
end
|
335
363
|
|