mongo 1.0 → 1.0.1
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/lib/mongo.rb +4 -1
- data/lib/mongo/collection.rb +36 -21
- data/lib/mongo/connection.rb +24 -7
- data/lib/mongo/cursor.rb +11 -5
- data/lib/mongo/db.rb +21 -11
- data/lib/mongo/exceptions.rb +3 -0
- data/lib/mongo/gridfs/grid.rb +10 -6
- data/lib/mongo/gridfs/grid_ext.rb +36 -9
- data/lib/mongo/gridfs/grid_file_system.rb +10 -7
- data/lib/mongo/gridfs/grid_io.rb +10 -8
- data/lib/mongo/util/conversions.rb +3 -1
- data/lib/mongo/util/core_ext.rb +2 -0
- data/lib/mongo/util/server_version.rb +2 -0
- data/lib/mongo/util/support.rb +2 -0
- data/test/auxillary/1.4_features.rb +1 -1
- data/test/collection_test.rb +45 -2
- data/test/connection_test.rb +0 -1
- data/test/cursor_test.rb +0 -1
- data/test/db_api_test.rb +15 -6
- data/test/db_connection_test.rb +0 -1
- data/test/db_test.rb +18 -1
- data/test/grid_file_system_test.rb +9 -0
- data/test/grid_test.rb +9 -0
- data/test/test_helper.rb +9 -1
- metadata +10 -19
data/lib/mongo.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
4
|
|
3
5
|
module Mongo
|
4
|
-
VERSION = "1.0"
|
6
|
+
VERSION = "1.0.1"
|
5
7
|
end
|
6
8
|
|
7
9
|
module Mongo
|
@@ -40,6 +42,7 @@ require 'mongo/connection'
|
|
40
42
|
require 'mongo/cursor'
|
41
43
|
require 'mongo/db'
|
42
44
|
require 'mongo/exceptions'
|
45
|
+
require 'mongo/gridfs/grid_ext'
|
43
46
|
require 'mongo/gridfs/grid'
|
44
47
|
require 'mongo/gridfs/grid_io'
|
45
48
|
require 'mongo/gridfs/grid_file_system'
|
data/lib/mongo/collection.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright (C) 2008-2010 10gen Inc.
|
3
5
|
#
|
@@ -203,17 +205,22 @@ module Mongo
|
|
203
205
|
#
|
204
206
|
# @return [ObjectID] the _id of the saved document.
|
205
207
|
#
|
206
|
-
# @option opts [Boolean] :safe (+false+)
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
210
|
-
|
208
|
+
# @option opts [Boolean, Hash] :safe (+false+)
|
209
|
+
# run the operation in safe mode, which run a getlasterror command on the
|
210
|
+
# database to report any assertion. In addition, a hash can be provided to
|
211
|
+
# run an fsync and/or wait for replication of the save (>= 1.5.1). See the options
|
212
|
+
# for DB#error.
|
213
|
+
#
|
214
|
+
# @raise [OperationFailure] when :safe mode fails.
|
215
|
+
#
|
216
|
+
# @see DB#remove for options that can be passed to :safe.
|
217
|
+
def save(doc, opts={})
|
211
218
|
if doc.has_key?(:_id) || doc.has_key?('_id')
|
212
219
|
id = doc[:_id] || doc['_id']
|
213
|
-
update({:_id => id}, doc, :upsert => true, :safe =>
|
220
|
+
update({:_id => id}, doc, :upsert => true, :safe => opts[:safe])
|
214
221
|
id
|
215
222
|
else
|
216
|
-
insert(doc, :safe =>
|
223
|
+
insert(doc, :safe => opts[:safe])
|
217
224
|
end
|
218
225
|
end
|
219
226
|
|
@@ -226,10 +233,13 @@ module Mongo
|
|
226
233
|
# the _id of the inserted document or a list of _ids of all inserted documents.
|
227
234
|
# Note: the object may have been modified by the database's PK factory, if it has one.
|
228
235
|
#
|
229
|
-
# @option opts [Boolean] :safe (+false+)
|
230
|
-
#
|
231
|
-
#
|
232
|
-
#
|
236
|
+
# @option opts [Boolean, Hash] :safe (+false+)
|
237
|
+
# run the operation in safe mode, which run a getlasterror command on the
|
238
|
+
# database to report any assertion. In addition, a hash can be provided to
|
239
|
+
# run an fsync and/or wait for replication of the insert (>= 1.5.1). See the options
|
240
|
+
# for DB#error.
|
241
|
+
#
|
242
|
+
# @see DB#remove for options that can be passed to :safe.
|
233
243
|
#
|
234
244
|
# @core insert insert-instance_method
|
235
245
|
def insert(doc_or_docs, options={})
|
@@ -245,8 +255,11 @@ module Mongo
|
|
245
255
|
# @param [Hash] selector
|
246
256
|
# If specified, only matching documents will be removed.
|
247
257
|
#
|
248
|
-
# @option opts [Boolean] :safe
|
249
|
-
#
|
258
|
+
# @option opts [Boolean, Hash] :safe (+false+)
|
259
|
+
# run the operation in safe mode, which run a getlasterror command on the
|
260
|
+
# database to report any assertion. In addition, a hash can be provided to
|
261
|
+
# run an fsync and/or wait for replication of the remove (>= 1.5.1). See the options
|
262
|
+
# for DB#error.
|
250
263
|
#
|
251
264
|
# @example remove all documents from the 'users' collection:
|
252
265
|
# users.remove
|
@@ -260,6 +273,8 @@ module Mongo
|
|
260
273
|
# @raise [Mongo::OperationFailure] an exception will be raised iff safe mode is enabled
|
261
274
|
# and the operation fails.
|
262
275
|
#
|
276
|
+
# @see DB#remove for options that can be passed to :safe.
|
277
|
+
#
|
263
278
|
# @core remove remove-instance_method
|
264
279
|
def remove(selector={}, opts={})
|
265
280
|
# Initial byte is 0.
|
@@ -270,7 +285,7 @@ module Mongo
|
|
270
285
|
|
271
286
|
if opts[:safe]
|
272
287
|
@connection.send_message_with_safe_check(Mongo::Constants::OP_DELETE, message, @db.name,
|
273
|
-
"#{@db.name}['#{@name}'].remove(#{selector.inspect})")
|
288
|
+
"#{@db.name}['#{@name}'].remove(#{selector.inspect})", opts[:safe])
|
274
289
|
# the return value of send_message_with_safe_check isn't actually meaningful --
|
275
290
|
# only the fact that it didn't raise an error is -- so just return true
|
276
291
|
true
|
@@ -312,7 +327,7 @@ module Mongo
|
|
312
327
|
message.put_array(BSON::BSON_CODER.serialize(document, false, true).to_a)
|
313
328
|
if options[:safe]
|
314
329
|
@connection.send_message_with_safe_check(Mongo::Constants::OP_UPDATE, message, @db.name,
|
315
|
-
"#{@db.name}['#{@name}'].update(#{selector.inspect}, #{document.inspect})")
|
330
|
+
"#{@db.name}['#{@name}'].update(#{selector.inspect}, #{document.inspect})", options[:safe])
|
316
331
|
else
|
317
332
|
@connection.send_message(Mongo::Constants::OP_UPDATE, message,
|
318
333
|
"#{@db.name}['#{@name}'].update(#{selector.inspect}, #{document.inspect})")
|
@@ -360,7 +375,7 @@ module Mongo
|
|
360
375
|
# @core indexes create_index-instance_method
|
361
376
|
def create_index(spec, opts={})
|
362
377
|
opts.assert_valid_keys(:min, :max, :background, :unique, :dropDups)
|
363
|
-
field_spec = OrderedHash.new
|
378
|
+
field_spec = BSON::OrderedHash.new
|
364
379
|
if spec.is_a?(String) || spec.is_a?(Symbol)
|
365
380
|
field_spec[spec.to_s] = 1
|
366
381
|
elsif spec.is_a?(Array) && spec.all? {|field| field.is_a?(Array) }
|
@@ -432,7 +447,7 @@ module Mongo
|
|
432
447
|
#
|
433
448
|
# @core findandmodify find_and_modify-instance_method
|
434
449
|
def find_and_modify(opts={})
|
435
|
-
cmd = OrderedHash.new
|
450
|
+
cmd = BSON::OrderedHash.new
|
436
451
|
cmd[:findandmodify] = @name
|
437
452
|
cmd.merge!(opts)
|
438
453
|
cmd[:sort] = Mongo::Support.format_order_clause(opts[:sort]) if opts[:sort]
|
@@ -465,7 +480,7 @@ module Mongo
|
|
465
480
|
map = BSON::Code.new(map) unless map.is_a?(BSON::Code)
|
466
481
|
reduce = BSON::Code.new(reduce) unless reduce.is_a?(BSON::Code)
|
467
482
|
|
468
|
-
hash = OrderedHash.new
|
483
|
+
hash = BSON::OrderedHash.new
|
469
484
|
hash['mapreduce'] = self.name
|
470
485
|
hash['map'] = map
|
471
486
|
hash['reduce'] = reduce
|
@@ -557,7 +572,7 @@ module Mongo
|
|
557
572
|
# @return [Array] an array of distinct values.
|
558
573
|
def distinct(key, query=nil)
|
559
574
|
raise MongoArgumentError unless [String, Symbol].include?(key.class)
|
560
|
-
command = OrderedHash.new
|
575
|
+
command = BSON::OrderedHash.new
|
561
576
|
command[:distinct] = @name
|
562
577
|
command[:key] = key.to_s
|
563
578
|
command[:query] = query
|
@@ -639,7 +654,7 @@ module Mongo
|
|
639
654
|
when nil
|
640
655
|
nil
|
641
656
|
else
|
642
|
-
h = OrderedHash.new
|
657
|
+
h = BSON::OrderedHash.new
|
643
658
|
hint.to_a.each { |k| h[k] = 1 }
|
644
659
|
h
|
645
660
|
end
|
@@ -657,7 +672,7 @@ module Mongo
|
|
657
672
|
documents.each { |doc| message.put_array(BSON::BSON_CODER.serialize(doc, check_keys, true).to_a) }
|
658
673
|
if safe
|
659
674
|
@connection.send_message_with_safe_check(Mongo::Constants::OP_INSERT, message, @db.name,
|
660
|
-
"#{@db.name}['#{collection_name}'].insert(#{documents.inspect})")
|
675
|
+
"#{@db.name}['#{collection_name}'].insert(#{documents.inspect})", safe)
|
661
676
|
else
|
662
677
|
@connection.send_message(Mongo::Constants::OP_INSERT, message,
|
663
678
|
"#{@db.name}['#{collection_name}'].insert(#{documents.inspect})")
|
data/lib/mongo/connection.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright (C) 2008-2010 10gen Inc.
|
3
5
|
#
|
@@ -172,6 +174,9 @@ module Mongo
|
|
172
174
|
# specificed in the list of auths. This method is called automatically
|
173
175
|
# by DB#authenticate.
|
174
176
|
#
|
177
|
+
# Note: this method will not actually issue an authentication command. To do that,
|
178
|
+
# either run Connection#apply_saved_authentication or DB#authenticate.
|
179
|
+
#
|
175
180
|
# @param [String] db_name
|
176
181
|
# @param [String] username
|
177
182
|
# @param [String] password
|
@@ -266,7 +271,7 @@ module Mongo
|
|
266
271
|
# @param [String] username username for authentication against from_db (>=1.3.x).
|
267
272
|
# @param [String] password password for authentication against from_db (>=1.3.x).
|
268
273
|
def copy_database(from, to, from_host="localhost", username=nil, password=nil)
|
269
|
-
oh = OrderedHash.new
|
274
|
+
oh = BSON::OrderedHash.new
|
270
275
|
oh[:copydb] = 1
|
271
276
|
oh[:fromhost] = from_host
|
272
277
|
oh[:fromdb] = from
|
@@ -275,7 +280,7 @@ module Mongo
|
|
275
280
|
unless username && password
|
276
281
|
raise MongoArgumentError, "Both username and password must be supplied for authentication."
|
277
282
|
end
|
278
|
-
nonce_cmd = OrderedHash.new
|
283
|
+
nonce_cmd = BSON::OrderedHash.new
|
279
284
|
nonce_cmd[:copydbgetnonce] = 1
|
280
285
|
nonce_cmd[:fromhost] = from_host
|
281
286
|
result = self["admin"].command(nonce_cmd, true, true)
|
@@ -347,13 +352,17 @@ module Mongo
|
|
347
352
|
# @param [BSON::ByteBuffer] message a message to send to the database.
|
348
353
|
# @param [String] db_name the name of the database. used on call to get_last_error.
|
349
354
|
# @param [String] log_message text version of +message+ for logging.
|
355
|
+
# @param [Hash] last_error_params parameters to be sent to getLastError. See DB#error for
|
356
|
+
# available options.
|
357
|
+
#
|
358
|
+
# @see DB#error for valid last error params.
|
350
359
|
#
|
351
360
|
# @return [Array]
|
352
361
|
# An array whose indexes include [0] documents returned, [1] number of document received,
|
353
362
|
# and [3] a cursor_id.
|
354
|
-
def send_message_with_safe_check(operation, message, db_name, log_message=nil)
|
363
|
+
def send_message_with_safe_check(operation, message, db_name, log_message=nil, last_error_params=false)
|
355
364
|
message_with_headers = add_message_headers(operation, message)
|
356
|
-
message_with_check = last_error_message(db_name)
|
365
|
+
message_with_check = last_error_message(db_name, last_error_params)
|
357
366
|
@logger.debug(" MONGODB #{log_message || message}") if @logger
|
358
367
|
begin
|
359
368
|
sock = checkout
|
@@ -366,7 +375,7 @@ module Mongo
|
|
366
375
|
ensure
|
367
376
|
checkin(sock)
|
368
377
|
end
|
369
|
-
if num_received == 1 && error = docs[0]['err']
|
378
|
+
if num_received == 1 && (error = docs[0]['err'] || docs[0]['errmsg'])
|
370
379
|
raise Mongo::OperationFailure, error
|
371
380
|
end
|
372
381
|
[docs, num_received, cursor_id]
|
@@ -644,13 +653,21 @@ module Mongo
|
|
644
653
|
[docs, number_received, cursor_id]
|
645
654
|
end
|
646
655
|
|
647
|
-
|
656
|
+
# Constructs a getlasterror message. This method is used exclusively by
|
657
|
+
# Connection#send_message_with_safe_check.
|
658
|
+
def last_error_message(db_name, opts)
|
648
659
|
message = BSON::ByteBuffer.new
|
649
660
|
message.put_int(0)
|
650
661
|
BSON::BSON_RUBY.serialize_cstr(message, "#{db_name}.$cmd")
|
651
662
|
message.put_int(0)
|
652
663
|
message.put_int(-1)
|
653
|
-
|
664
|
+
cmd = BSON::OrderedHash.new
|
665
|
+
cmd[:getlasterror] = 1
|
666
|
+
if opts.is_a?(Hash)
|
667
|
+
opts.assert_valid_keys(:w, :wtimeout, :fsync)
|
668
|
+
cmd.merge!(opts)
|
669
|
+
end
|
670
|
+
message.put_array(BSON::BSON_CODER.serialize(cmd, false).unpack("C*"))
|
654
671
|
add_message_headers(Mongo::Constants::OP_QUERY, message)
|
655
672
|
end
|
656
673
|
|
data/lib/mongo/cursor.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
# Copyright (C) 2008-2010 10gen Inc.
|
2
4
|
#
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -94,7 +96,7 @@ module Mongo
|
|
94
96
|
#
|
95
97
|
# @raise [OperationFailure] on a database error.
|
96
98
|
def count
|
97
|
-
command = OrderedHash["count", @collection.name,
|
99
|
+
command = BSON::OrderedHash["count", @collection.name,
|
98
100
|
"query", @selector,
|
99
101
|
"fields", @fields]
|
100
102
|
response = @db.command(command)
|
@@ -299,10 +301,14 @@ module Mongo
|
|
299
301
|
selector
|
300
302
|
when nil
|
301
303
|
{}
|
302
|
-
when
|
303
|
-
|
304
|
-
|
304
|
+
when BSON::Code
|
305
|
+
warn "Collection#find will no longer take a JavaScript string in future versions. " +
|
306
|
+
"Please specify your $where query explicitly."
|
305
307
|
{"$where" => selector}
|
308
|
+
when String
|
309
|
+
warn "Collection#find will no longer take a JavaScript string in future versions. " +
|
310
|
+
"Please specify your $where query explicitly."
|
311
|
+
{"$where" => BSON::Code.new(selector)}
|
306
312
|
end
|
307
313
|
end
|
308
314
|
|
@@ -366,7 +372,7 @@ module Mongo
|
|
366
372
|
|
367
373
|
def construct_query_spec
|
368
374
|
return @selector if @selector.has_key?('$query')
|
369
|
-
spec = OrderedHash.new
|
375
|
+
spec = BSON::OrderedHash.new
|
370
376
|
spec['$query'] = @selector
|
371
377
|
spec['$orderby'] = Mongo::Support.format_order_clause(@order) if @order
|
372
378
|
spec['$hint'] = @hint if @hint && @hint.length > 0
|
data/lib/mongo/db.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright (C) 2008-2010 10gen Inc.
|
3
5
|
#
|
@@ -89,7 +91,7 @@ module Mongo
|
|
89
91
|
raise "error retrieving nonce: #{doc}" unless ok?(doc)
|
90
92
|
nonce = doc['nonce']
|
91
93
|
|
92
|
-
auth = OrderedHash.new
|
94
|
+
auth = BSON::OrderedHash.new
|
93
95
|
auth['authenticate'] = 1
|
94
96
|
auth['user'] = username
|
95
97
|
auth['nonce'] = nonce
|
@@ -212,7 +214,7 @@ module Mongo
|
|
212
214
|
end
|
213
215
|
|
214
216
|
# Create a new collection.
|
215
|
-
oh = OrderedHash.new
|
217
|
+
oh = BSON::OrderedHash.new
|
216
218
|
oh[:create] = name
|
217
219
|
doc = command(oh.merge(options || {}))
|
218
220
|
ok = doc['ok']
|
@@ -247,11 +249,19 @@ module Mongo
|
|
247
249
|
# Get the error message from the most recently executed database
|
248
250
|
# operation for this connection.
|
249
251
|
#
|
250
|
-
# @
|
252
|
+
# @option opts [Boolean] :fsync (false)
|
253
|
+
# @option opts [Integer] :w (nil)
|
254
|
+
# @option opts [Integer] :wtimeout (nil)
|
255
|
+
#
|
256
|
+
# @return [String, Nil] either the text describing an error or nil if no
|
251
257
|
# error has occurred.
|
252
|
-
def error
|
253
|
-
|
254
|
-
|
258
|
+
def error(opts={})
|
259
|
+
opts.assert_valid_keys(:w, :wtimeout, :fsync)
|
260
|
+
cmd = BSON::OrderedHash.new
|
261
|
+
cmd[:getlasterror] = 1
|
262
|
+
cmd.merge!(opts) unless opts.empty?
|
263
|
+
doc = command(cmd)
|
264
|
+
raise MongoDBError, "error retrieving last error: #{doc.inspect}" unless ok?(doc)
|
255
265
|
doc['err']
|
256
266
|
end
|
257
267
|
|
@@ -329,7 +339,7 @@ module Mongo
|
|
329
339
|
code = BSON::Code.new(code)
|
330
340
|
end
|
331
341
|
|
332
|
-
oh = OrderedHash.new
|
342
|
+
oh = BSON::OrderedHash.new
|
333
343
|
oh[:$eval] = code
|
334
344
|
oh[:args] = args
|
335
345
|
doc = command(oh)
|
@@ -346,7 +356,7 @@ module Mongo
|
|
346
356
|
#
|
347
357
|
# @raise MongoDBError if there's an error renaming the collection.
|
348
358
|
def rename_collection(from, to)
|
349
|
-
oh = OrderedHash.new
|
359
|
+
oh = BSON::OrderedHash.new
|
350
360
|
oh[:renameCollection] = "#{@name}.#{from}"
|
351
361
|
oh[:to] = "#{@name}.#{to}"
|
352
362
|
doc = command(oh, true)
|
@@ -363,7 +373,7 @@ module Mongo
|
|
363
373
|
#
|
364
374
|
# @raise MongoDBError if there's an error renaming the collection.
|
365
375
|
def drop_index(collection_name, index_name)
|
366
|
-
oh = OrderedHash.new
|
376
|
+
oh = BSON::OrderedHash.new
|
367
377
|
oh[:deleteIndexes] = collection_name
|
368
378
|
oh[:index] = index_name
|
369
379
|
doc = command(oh)
|
@@ -494,7 +504,7 @@ module Mongo
|
|
494
504
|
#
|
495
505
|
# @core profiling profiling_level-instance_method
|
496
506
|
def profiling_level
|
497
|
-
oh = OrderedHash.new
|
507
|
+
oh = BSON::OrderedHash.new
|
498
508
|
oh[:profile] = -1
|
499
509
|
doc = command(oh)
|
500
510
|
raise "Error with profile command: #{doc.inspect}" unless ok?(doc) && doc['was'].kind_of?(Numeric)
|
@@ -515,7 +525,7 @@ module Mongo
|
|
515
525
|
#
|
516
526
|
# @param [Symbol] level acceptable options are +:off+, +:slow_only+, or +:all+.
|
517
527
|
def profiling_level=(level)
|
518
|
-
oh = OrderedHash.new
|
528
|
+
oh = BSON::OrderedHash.new
|
519
529
|
oh[:profile] = case level
|
520
530
|
when :off
|
521
531
|
0
|
data/lib/mongo/exceptions.rb
CHANGED
data/lib/mongo/gridfs/grid.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright (C) 2008-2010 10gen Inc.
|
3
5
|
#
|
@@ -18,6 +20,8 @@ module Mongo
|
|
18
20
|
|
19
21
|
# Implementation of the MongoDB GridFS specification. A file store.
|
20
22
|
class Grid
|
23
|
+
include GridExt::InstanceMethods
|
24
|
+
|
21
25
|
DEFAULT_FS_NAME = 'fs'
|
22
26
|
|
23
27
|
# Initialize a new Grid instance, consisting of a MongoDB database
|
@@ -44,15 +48,15 @@ module Mongo
|
|
44
48
|
#
|
45
49
|
# @param [String, #read] data a string or io-like object to store.
|
46
50
|
#
|
47
|
-
# @
|
48
|
-
# @
|
49
|
-
# @
|
51
|
+
# @option opts [String] :filename (nil) a name for the file.
|
52
|
+
# @option opts [Hash] :metadata ({}) any additional data to store with the file.
|
53
|
+
# @option opts [ObjectID] :_id (ObjectID) a unique id for
|
50
54
|
# the file to be use in lieu of an automatically generated one.
|
51
|
-
# @
|
55
|
+
# @option opts [String] :content_type ('binary/octet-stream') If no content type is specified,
|
52
56
|
# the content type will may be inferred from the filename extension if the mime-types gem can be
|
53
57
|
# loaded. Otherwise, the content type 'binary/octet-stream' will be used.
|
54
|
-
# @
|
55
|
-
# @
|
58
|
+
# @option opts [Integer] (262144) :chunk_size size of file chunks in bytes.
|
59
|
+
# @option opts [Boolean] :safe (false) When safe mode is enabled, the chunks sent to the server
|
56
60
|
# will be validated using an md5 hash. If validation fails, an exception will be raised.
|
57
61
|
#
|
58
62
|
# @return [Mongo::ObjectID] the file's id.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright (C) 2008-2010 10gen Inc.
|
3
5
|
#
|
@@ -15,16 +17,41 @@
|
|
15
17
|
# ++
|
16
18
|
|
17
19
|
module Mongo
|
18
|
-
module
|
19
|
-
|
20
|
-
def exists?(criteria)
|
21
|
-
BSON::ObjectID:
|
22
|
-
@files.find_one(query)
|
23
|
-
end
|
20
|
+
module GridExt
|
21
|
+
module InstanceMethods
|
24
22
|
|
25
|
-
|
26
|
-
|
23
|
+
# Check the existence of a file matching the given query selector.
|
24
|
+
#
|
25
|
+
# Note that this method can be used with both the Grid and GridFileSystem classes. Also
|
26
|
+
# keep in mind that if you're going to be performing lots of existence checks, you should
|
27
|
+
# keep an instance of Grid or GridFileSystem handy rather than instantiating for each existence
|
28
|
+
# check. Alternatively, simply keep a reference to the proper files collection and query that
|
29
|
+
# as needed. That's exactly how this methods works.
|
30
|
+
#
|
31
|
+
# @param [Hash] selector a query selector.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
#
|
35
|
+
# # Check for the existence of a given filename
|
36
|
+
# @grid = GridFileSystem.new(@db)
|
37
|
+
# @grid.exist?(:filename => 'foo.txt')
|
38
|
+
#
|
39
|
+
# # Check for existence filename and content type
|
40
|
+
# @grid = GridFileSystem.new(@db)
|
41
|
+
# @grid.exist?(:filename => 'foo.txt', :content_type => 'image/jpg')
|
42
|
+
#
|
43
|
+
# # Check for existence by _id
|
44
|
+
# @grid = Grid.new(@db)
|
45
|
+
# @grid.exist?(:_id => BSON::ObjectID.from_string('4bddcd24beffd95a7db9b8c8'))
|
46
|
+
#
|
47
|
+
# # Check for existence by an arbitrary attribute.
|
48
|
+
# @grid = Grid.new(@db)
|
49
|
+
# @grid.exist?(:tags => {'$in' => ['nature', 'zen', 'photography']})
|
50
|
+
#
|
51
|
+
# @return [nil, Hash] either nil for the file's metadata as a hash.
|
52
|
+
def exist?(selector)
|
53
|
+
@files.find_one(selector)
|
54
|
+
end
|
27
55
|
end
|
28
|
-
|
29
56
|
end
|
30
57
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright (C) 2008-2010 10gen Inc.
|
3
5
|
#
|
@@ -19,8 +21,9 @@ module Mongo
|
|
19
21
|
# A file store built on the GridFS specification featuring
|
20
22
|
# an API and behavior similar to that of a traditional file system.
|
21
23
|
class GridFileSystem
|
24
|
+
include GridExt::InstanceMethods
|
22
25
|
|
23
|
-
# Initialize a new
|
26
|
+
# Initialize a new GridFileSystem instance, consisting of a MongoDB database
|
24
27
|
# and a filesystem prefix if not using the default.
|
25
28
|
#
|
26
29
|
# @param [Mongo::DB] db a MongoDB database.
|
@@ -51,17 +54,17 @@ module Mongo
|
|
51
54
|
# or writing to the file.
|
52
55
|
# @param [Hash] opts see GridIO#new
|
53
56
|
#
|
54
|
-
# @
|
55
|
-
# @
|
57
|
+
# @option opts [Hash] :metadata ({}) any additional data to store with the file.
|
58
|
+
# @option opts [ObjectID] :_id (ObjectID) a unique id for
|
56
59
|
# the file to be use in lieu of an automatically generated one.
|
57
|
-
# @
|
60
|
+
# @option opts [String] :content_type ('binary/octet-stream') If no content type is specified,
|
58
61
|
# the content type will may be inferred from the filename extension if the mime-types gem can be
|
59
62
|
# loaded. Otherwise, the content type 'binary/octet-stream' will be used.
|
60
|
-
# @
|
61
|
-
# @
|
63
|
+
# @option opts [Integer] (262144) :chunk_size size of file chunks in bytes.
|
64
|
+
# @option opts [Boolean] :delete_old (false) ensure that old versions of the file are deleted. This option
|
62
65
|
# only work in 'w' mode. Certain precautions must be taken when deleting GridFS files. See the notes under
|
63
66
|
# GridFileSystem#delete.
|
64
|
-
# @
|
67
|
+
# @option opts [Boolean] :safe (false) When safe mode is enabled, the chunks sent to the server
|
65
68
|
# will be validated using an md5 hash. If validation fails, an exception will be raised.
|
66
69
|
#
|
67
70
|
# @example
|
data/lib/mongo/gridfs/grid_io.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright (C) 2008-2010 10gen Inc.
|
3
5
|
#
|
@@ -43,14 +45,14 @@ module Mongo
|
|
43
45
|
# @option opts [Hash] :query a query selector used when opening the file in 'r' mode.
|
44
46
|
# @option opts [Hash] :query_opts any query options to be used when opening the file in 'r' mode.
|
45
47
|
# @option opts [String] :fs_name the file system prefix.
|
46
|
-
# @
|
47
|
-
# @
|
48
|
-
# @
|
48
|
+
# @option opts [Integer] (262144) :chunk_size size of file chunks in bytes.
|
49
|
+
# @option opts [Hash] :metadata ({}) any additional data to store with the file.
|
50
|
+
# @option opts [ObjectID] :_id (ObjectID) a unique id for
|
49
51
|
# the file to be use in lieu of an automatically generated one.
|
50
|
-
# @
|
52
|
+
# @option opts [String] :content_type ('binary/octet-stream') If no content type is specified,
|
51
53
|
# the content type will may be inferred from the filename extension if the mime-types gem can be
|
52
54
|
# loaded. Otherwise, the content type 'binary/octet-stream' will be used.
|
53
|
-
# @
|
55
|
+
# @option opts [Boolean] :safe (false) When safe mode is enabled, the chunks sent to the server
|
54
56
|
# will be validated using an md5 hash. If validation fails, an exception will be raised.
|
55
57
|
def initialize(files, chunks, filename, mode, opts={})
|
56
58
|
@files = files
|
@@ -197,7 +199,7 @@ module Mongo
|
|
197
199
|
private
|
198
200
|
|
199
201
|
def create_chunk(n)
|
200
|
-
chunk = OrderedHash.new
|
202
|
+
chunk = BSON::OrderedHash.new
|
201
203
|
chunk['_id'] = BSON::ObjectID.new
|
202
204
|
chunk['n'] = n
|
203
205
|
chunk['files_id'] = @files_id
|
@@ -319,7 +321,7 @@ module Mongo
|
|
319
321
|
end
|
320
322
|
|
321
323
|
def to_mongo_object
|
322
|
-
h = OrderedHash.new
|
324
|
+
h = BSON::OrderedHash.new
|
323
325
|
h['_id'] = @files_id
|
324
326
|
h['filename'] = @filename if @filename
|
325
327
|
h['contentType'] = @content_type
|
@@ -335,7 +337,7 @@ module Mongo
|
|
335
337
|
|
336
338
|
# Get a server-side md5 and validate against the client if running in safe mode.
|
337
339
|
def get_md5
|
338
|
-
md5_command = OrderedHash.new
|
340
|
+
md5_command = BSON::OrderedHash.new
|
339
341
|
md5_command['filemd5'] = @files_id
|
340
342
|
md5_command['root'] = @fs_name
|
341
343
|
@server_md5 = @files.db.command(md5_command)['md5']
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright (C) 2008-2010 10gen Inc.
|
3
5
|
#
|
@@ -31,7 +33,7 @@ module Mongo #:nodoc:
|
|
31
33
|
# <tt>array_as_sort_parameters([["field1", :asc], ["field2", :desc]])</tt> =>
|
32
34
|
# <tt>{ "field1" => 1, "field2" => -1}</tt>
|
33
35
|
def array_as_sort_parameters(value)
|
34
|
-
order_by = OrderedHash.new
|
36
|
+
order_by = BSON::OrderedHash.new
|
35
37
|
if value.first.is_a? Array
|
36
38
|
value.each do |param|
|
37
39
|
if (param.class.name == "String")
|
data/lib/mongo/util/core_ext.rb
CHANGED
data/lib/mongo/util/support.rb
CHANGED
@@ -150,7 +150,7 @@ class Features14Test < Test::Unit::TestCase
|
|
150
150
|
end
|
151
151
|
|
152
152
|
should "use geoNear command to return distances from a point" do
|
153
|
-
cmd = OrderedHash.new
|
153
|
+
cmd = BSON::OrderedHash.new
|
154
154
|
cmd['geoNear'] = 'places'
|
155
155
|
cmd['near'] = @empire_state
|
156
156
|
cmd['num'] = 6
|
data/test/collection_test.rb
CHANGED
@@ -115,6 +115,39 @@ class TestCollection < Test::Unit::TestCase
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
118
|
+
if @@version >= "1.5.1"
|
119
|
+
def test_safe_mode_with_advanced_safe_with_invalid_options
|
120
|
+
assert_raise_error ArgumentError, "Unknown key(s): wtime" do
|
121
|
+
@@test.insert({:foo => 1}, :safe => {:w => 2, :wtime => 1, :fsync => true})
|
122
|
+
end
|
123
|
+
assert_raise_error ArgumentError, "Unknown key(s): wtime" do
|
124
|
+
@@test.update({:foo => 1}, {:foo => 2}, :safe => {:w => 2, :wtime => 1, :fsync => true})
|
125
|
+
end
|
126
|
+
|
127
|
+
assert_raise_error ArgumentError, "Unknown key(s): wtime" do
|
128
|
+
@@test.remove({:foo => 2}, :safe => {:w => 2, :wtime => 1, :fsync => true})
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_safe_mode_with_w_failure
|
133
|
+
assert_raise_error OperationFailure, "timed out waiting for slaves" do
|
134
|
+
@@test.insert({:foo => 1}, :safe => {:w => 2, :wtimeout => 1, :fsync => true})
|
135
|
+
end
|
136
|
+
assert_raise_error OperationFailure, "timed out waiting for slaves" do
|
137
|
+
@@test.update({:foo => 1}, {:foo => 2}, :safe => {:w => 2, :wtimeout => 1, :fsync => true})
|
138
|
+
end
|
139
|
+
assert_raise_error OperationFailure, "timed out waiting for slaves" do
|
140
|
+
@@test.remove({:foo => 2}, :safe => {:w => 2, :wtimeout => 1, :fsync => true})
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_safe_mode_with_write_and_fsync
|
145
|
+
assert @@test.insert({:foo => 1}, :safe => {:w => 1, :wtimeout => 1, :fsync => true})
|
146
|
+
assert @@test.update({:foo => 1}, {:foo => 2}, :safe => {:w => 1, :wtimeout => 1, :fsync => true})
|
147
|
+
assert @@test.remove({:foo => 2}, :safe => {:w => 1, :wtimeout => 1, :fsync => true})
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
118
151
|
def test_update
|
119
152
|
id1 = @@test.save("x" => 5)
|
120
153
|
@@test.update({}, {"$inc" => {"x" => 1}})
|
@@ -272,6 +305,16 @@ class TestCollection < Test::Unit::TestCase
|
|
272
305
|
end
|
273
306
|
end
|
274
307
|
|
308
|
+
if @@version >= "1.5.1"
|
309
|
+
def test_fields_with_slice
|
310
|
+
@@test.save({:foo => [1, 2, 3, 4, 5, 6], :test => 'slice'})
|
311
|
+
|
312
|
+
doc = @@test.find_one({:test => 'slice'}, :fields => {'foo' => {'$slice' => [0, 3]}})
|
313
|
+
assert_equal [1, 2, 3], doc['foo']
|
314
|
+
@@test.remove
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
275
318
|
def test_find_one
|
276
319
|
id = @@test.save("hello" => "world", "foo" => "bar")
|
277
320
|
|
@@ -280,14 +323,14 @@ class TestCollection < Test::Unit::TestCase
|
|
280
323
|
assert_equal @@test.find_one(nil), @@test.find_one()
|
281
324
|
assert_equal @@test.find_one({}), @@test.find_one()
|
282
325
|
assert_equal @@test.find_one("hello" => "world"), @@test.find_one()
|
283
|
-
assert_equal @@test.find_one(OrderedHash["hello", "world"]), @@test.find_one()
|
326
|
+
assert_equal @@test.find_one(BSON::OrderedHash["hello", "world"]), @@test.find_one()
|
284
327
|
|
285
328
|
assert @@test.find_one(nil, :fields => ["hello"]).include?("hello")
|
286
329
|
assert !@@test.find_one(nil, :fields => ["foo"]).include?("hello")
|
287
330
|
assert_equal ["_id"], @@test.find_one(nil, :fields => []).keys()
|
288
331
|
|
289
332
|
assert_equal nil, @@test.find_one("hello" => "foo")
|
290
|
-
assert_equal nil, @@test.find_one(OrderedHash["hello", "foo"])
|
333
|
+
assert_equal nil, @@test.find_one(BSON::OrderedHash["hello", "foo"])
|
291
334
|
assert_equal nil, @@test.find_one(ObjectID.new)
|
292
335
|
|
293
336
|
assert_raise TypeError do
|
data/test/connection_test.rb
CHANGED
data/test/cursor_test.rb
CHANGED
data/test/db_api_test.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'test/test_helper'
|
2
2
|
|
3
|
-
# NOTE: assumes Mongo is running
|
4
3
|
class DBAPITest < Test::Unit::TestCase
|
5
4
|
include Mongo
|
6
5
|
include BSON
|
@@ -47,14 +46,14 @@ class DBAPITest < Test::Unit::TestCase
|
|
47
46
|
end
|
48
47
|
|
49
48
|
def test_save_ordered_hash
|
50
|
-
oh = OrderedHash.new
|
49
|
+
oh = BSON::OrderedHash.new
|
51
50
|
oh['a'] = -1
|
52
51
|
oh['b'] = 'foo'
|
53
52
|
|
54
53
|
oid = @@coll.save(oh)
|
55
54
|
assert_equal 'foo', @@coll.find_one(oid)['b']
|
56
55
|
|
57
|
-
oh = OrderedHash['a' => 1, 'b' => 'foo']
|
56
|
+
oh = BSON::OrderedHash['a' => 1, 'b' => 'foo']
|
58
57
|
oid = @@coll.save(oh)
|
59
58
|
assert_equal 'foo', @@coll.find_one(oid)['b']
|
60
59
|
end
|
@@ -188,7 +187,7 @@ class DBAPITest < Test::Unit::TestCase
|
|
188
187
|
|
189
188
|
# Sorting using ordered hash. You can use an unordered one, but then the
|
190
189
|
# order of the keys won't be guaranteed thus your sort won't make sense.
|
191
|
-
oh = OrderedHash.new
|
190
|
+
oh = BSON::OrderedHash.new
|
192
191
|
oh['a'] = -1
|
193
192
|
assert_raise InvalidSortValueError do
|
194
193
|
docs = @@coll.find({'a' => { '$lt' => 10 }}, :sort => oh).to_a
|
@@ -470,8 +469,18 @@ class DBAPITest < Test::Unit::TestCase
|
|
470
469
|
@@coll.insert('a' => 3)
|
471
470
|
|
472
471
|
assert_equal 3, @@coll.count
|
473
|
-
assert_equal 1, @@coll.find('$where' => Code.new('this.a > 2')).count()
|
474
|
-
assert_equal 2, @@coll.find('$where' => Code.new('this.a > i', {'i' => 1})).count()
|
472
|
+
assert_equal 1, @@coll.find('$where' => BSON::Code.new('this.a > 2')).count()
|
473
|
+
assert_equal 2, @@coll.find('$where' => BSON::Code.new('this.a > i', {'i' => 1})).count()
|
474
|
+
end
|
475
|
+
|
476
|
+
def test_implicit_where
|
477
|
+
@@coll.remove
|
478
|
+
@@coll.insert('a' => 2)
|
479
|
+
@@coll.insert('a' => 3)
|
480
|
+
|
481
|
+
assert_equal 2, @@coll.count
|
482
|
+
assert_equal 1, @@coll.find('this.a > 2').count()
|
483
|
+
assert_equal 2, @@coll.find(BSON::Code.new('this.a > z', {'z' => 1})).to_a.length
|
475
484
|
end
|
476
485
|
|
477
486
|
def test_eval
|
data/test/db_connection_test.rb
CHANGED
data/test/db_test.rb
CHANGED
@@ -10,7 +10,6 @@ class TestPKFactory
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
# NOTE: assumes Mongo is running
|
14
13
|
class DBTest < Test::Unit::TestCase
|
15
14
|
|
16
15
|
include Mongo
|
@@ -183,6 +182,24 @@ class DBTest < Test::Unit::TestCase
|
|
183
182
|
assert_nil @@db.previous_error
|
184
183
|
end
|
185
184
|
|
185
|
+
if @@version >= "1.5.1"
|
186
|
+
def test_failing_error_params
|
187
|
+
assert_raise_error Mongo::MongoDBError, "timed out waiting for slaves" do
|
188
|
+
@@db.error(:w => 2, :wtimeout => 10, :fsync => true)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_passing_error_params
|
193
|
+
assert_nil @@db.error(:w => 1, :wtimeout => 10, :fsync => true)
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_invalid_error_params
|
197
|
+
assert_raise_error ArgumentError, "Unknown key(s): z" do
|
198
|
+
@@db.error(:z => 1, :wtimeout => 10, :fsync => true)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
186
203
|
def test_check_command_response
|
187
204
|
command = {:forceerror => 1}
|
188
205
|
assert_raise OperationFailure do
|
@@ -25,6 +25,15 @@ class GridFileSystemTest < Test::Unit::TestCase
|
|
25
25
|
@grid = GridFileSystem.new(@db)
|
26
26
|
end
|
27
27
|
|
28
|
+
should "return existence of the file" do
|
29
|
+
file = @grid.exist?(:filename => 'sample.file')
|
30
|
+
assert_equal 'sample.file', file['filename']
|
31
|
+
end
|
32
|
+
|
33
|
+
should "return nil if the file doesn't exist" do
|
34
|
+
assert_nil @grid.exist?(:filename => 'foo.file')
|
35
|
+
end
|
36
|
+
|
28
37
|
should "read sample data" do
|
29
38
|
data = @grid.open('sample.file', 'r') { |f| f.read }
|
30
39
|
assert_equal data.length, @chunks_data.length
|
data/test/grid_test.rb
CHANGED
@@ -22,6 +22,15 @@ class GridTest < Test::Unit::TestCase
|
|
22
22
|
@id = @grid.put(@data, :filename => 'sample', :metadata => {'app' => 'photos'})
|
23
23
|
end
|
24
24
|
|
25
|
+
should "check existence" do
|
26
|
+
file = @grid.exist?(:filename => 'sample')
|
27
|
+
assert_equal 'sample', file['filename']
|
28
|
+
end
|
29
|
+
|
30
|
+
should "return nil if it doesn't exist" do
|
31
|
+
assert_nil @grid.exist?(:metadata => 'foo')
|
32
|
+
end
|
33
|
+
|
25
34
|
should "retrieve the stored data" do
|
26
35
|
data = @grid.get(@id).data
|
27
36
|
assert_equal @data, data
|
data/test/test_helper.rb
CHANGED
@@ -23,7 +23,6 @@ require 'bson_ext/cbson' if ENV['C_EXT']
|
|
23
23
|
|
24
24
|
MONGO_TEST_DB = 'mongo-ruby-test'
|
25
25
|
|
26
|
-
# NOTE: most tests assume that MongoDB is running.
|
27
26
|
class Test::Unit::TestCase
|
28
27
|
include Mongo
|
29
28
|
include BSON
|
@@ -42,4 +41,13 @@ class Test::Unit::TestCase
|
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|
44
|
+
|
45
|
+
def assert_raise_error(klass, message)
|
46
|
+
begin
|
47
|
+
yield
|
48
|
+
rescue => e
|
49
|
+
assert_equal klass, e.class
|
50
|
+
assert e.message.include?(message), "#{e.message} does not include #{message}."
|
51
|
+
end
|
52
|
+
end
|
45
53
|
end
|
metadata
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
segments:
|
6
|
-
- 1
|
7
|
-
- 0
|
8
|
-
version: "1.0"
|
4
|
+
version: 1.0.1
|
9
5
|
platform: ruby
|
10
6
|
authors:
|
11
7
|
- Jim Menard
|
@@ -15,22 +11,19 @@ autorequire:
|
|
15
11
|
bindir: bin
|
16
12
|
cert_chain: []
|
17
13
|
|
18
|
-
date: 2010-
|
14
|
+
date: 2010-05-07 00:00:00 -04:00
|
19
15
|
default_executable:
|
20
16
|
dependencies:
|
21
17
|
- !ruby/object:Gem::Dependency
|
22
18
|
name: bson
|
23
|
-
|
24
|
-
|
19
|
+
type: :runtime
|
20
|
+
version_requirement:
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
22
|
requirements:
|
26
23
|
- - "="
|
27
24
|
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
|
30
|
-
- 0
|
31
|
-
version: "1.0"
|
32
|
-
type: :runtime
|
33
|
-
version_requirements: *id001
|
25
|
+
version: 1.0.1
|
26
|
+
version:
|
34
27
|
description: A Ruby driver for MongoDB. For more information about Mongo, see http://www.mongodb.org.
|
35
28
|
email: mongodb-dev@googlegroups.com
|
36
29
|
executables: []
|
@@ -85,20 +78,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
78
|
requirements:
|
86
79
|
- - ">="
|
87
80
|
- !ruby/object:Gem::Version
|
88
|
-
segments:
|
89
|
-
- 0
|
90
81
|
version: "0"
|
82
|
+
version:
|
91
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
84
|
requirements:
|
93
85
|
- - ">="
|
94
86
|
- !ruby/object:Gem::Version
|
95
|
-
segments:
|
96
|
-
- 0
|
97
87
|
version: "0"
|
88
|
+
version:
|
98
89
|
requirements: []
|
99
90
|
|
100
91
|
rubyforge_project:
|
101
|
-
rubygems_version: 1.3.
|
92
|
+
rubygems_version: 1.3.5
|
102
93
|
signing_key:
|
103
94
|
specification_version: 3
|
104
95
|
summary: Ruby driver for the MongoDB
|