mongo 0.18.3 → 0.19
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 +41 -50
- data/Rakefile +14 -4
- data/examples/gridfs.rb +25 -70
- data/lib/mongo.rb +4 -2
- data/lib/mongo/collection.rb +70 -89
- data/lib/mongo/connection.rb +203 -43
- data/lib/mongo/cursor.rb +7 -7
- data/lib/mongo/db.rb +61 -18
- data/lib/mongo/exceptions.rb +7 -1
- data/lib/mongo/gridfs.rb +8 -1
- data/lib/mongo/gridfs/chunk.rb +2 -1
- data/lib/mongo/gridfs/grid.rb +90 -0
- data/lib/mongo/gridfs/grid_file_system.rb +113 -0
- data/lib/mongo/gridfs/grid_io.rb +339 -0
- data/lib/mongo/gridfs/grid_store.rb +43 -18
- data/lib/mongo/types/binary.rb +5 -1
- data/lib/mongo/types/code.rb +1 -1
- data/lib/mongo/types/dbref.rb +3 -1
- data/lib/mongo/types/min_max_keys.rb +1 -1
- data/lib/mongo/types/objectid.rb +16 -55
- data/lib/mongo/types/regexp_of_holding.rb +1 -1
- data/lib/mongo/util/bson_c.rb +2 -2
- data/lib/mongo/util/bson_ruby.rb +22 -11
- data/lib/mongo/util/byte_buffer.rb +1 -1
- data/lib/mongo/util/conversions.rb +1 -1
- data/lib/mongo/util/ordered_hash.rb +6 -1
- data/lib/mongo/util/server_version.rb +1 -1
- data/lib/mongo/util/support.rb +1 -1
- data/mongo-ruby-driver.gemspec +1 -1
- data/test/auxillary/authentication_test.rb +68 -0
- data/test/auxillary/autoreconnect_test.rb +41 -0
- data/test/binary_test.rb +15 -0
- data/test/{test_bson.rb → bson_test.rb} +63 -6
- data/test/{test_byte_buffer.rb → byte_buffer_test.rb} +0 -0
- data/test/{test_chunk.rb → chunk_test.rb} +0 -0
- data/test/{test_collection.rb → collection_test.rb} +35 -39
- data/test/{test_connection.rb → connection_test.rb} +33 -3
- data/test/{test_conversions.rb → conversions_test.rb} +0 -0
- data/test/{test_cursor.rb → cursor_test.rb} +0 -7
- data/test/{test_db_api.rb → db_api_test.rb} +3 -6
- data/test/{test_db_connection.rb → db_connection_test.rb} +0 -0
- data/test/{test_db.rb → db_test.rb} +33 -15
- data/test/grid_file_system_test.rb +210 -0
- data/test/grid_io_test.rb +78 -0
- data/test/{test_grid_store.rb → grid_store_test.rb} +33 -2
- data/test/grid_test.rb +87 -0
- data/test/{test_objectid.rb → objectid_test.rb} +2 -33
- data/test/{test_ordered_hash.rb → ordered_hash_test.rb} +4 -0
- data/test/{test_slave_connection.rb → slave_connection_test.rb} +0 -0
- data/test/test_helper.rb +2 -2
- data/test/{test_threading.rb → threading_test.rb} +0 -0
- data/test/unit/collection_test.rb +12 -3
- data/test/unit/connection_test.rb +85 -24
- data/test/unit/cursor_test.rb +1 -2
- data/test/unit/db_test.rb +70 -69
- metadata +27 -23
- data/bin/objectid_benchmark.rb +0 -23
- data/bin/perf.rb +0 -30
- data/lib/mongo/admin.rb +0 -95
- data/lib/mongo/util/xml_to_ruby.rb +0 -112
- data/test/test_admin.rb +0 -67
- data/test/test_round_trip.rb +0 -114
data/README.rdoc
CHANGED
@@ -9,15 +9,15 @@ Here's a quick code sample. See the MongoDB Ruby Tutorial
|
|
9
9
|
require 'mongo'
|
10
10
|
include Mongo
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
db = Connection.new.db('sample-db')
|
13
|
+
coll = db.collection('test')
|
14
14
|
|
15
|
-
|
15
|
+
coll.remove
|
16
16
|
3.times do |i|
|
17
|
-
|
17
|
+
coll.insert({'a' => i+1})
|
18
18
|
end
|
19
|
-
puts "There are #{
|
20
|
-
|
19
|
+
puts "There are #{coll.count()} records. Here they are:"
|
20
|
+
coll.find().each { |doc| puts doc.inspect }
|
21
21
|
|
22
22
|
= Installation
|
23
23
|
|
@@ -25,7 +25,6 @@ The driver's gems are hosted on Gemcutter[http://gemcutter.org]. If you haven't
|
|
25
25
|
installed a gem from Gemcutter before, you'll need to set up Gemcutter first:
|
26
26
|
|
27
27
|
$ gem install gemcutter
|
28
|
-
$ gem tumble
|
29
28
|
|
30
29
|
Once you've installed Gemcutter, install the mongo gem as follows:
|
31
30
|
|
@@ -70,40 +69,51 @@ Here's how to start MongoDB and run the "simple.rb" example:
|
|
70
69
|
|
71
70
|
See also the test code, especially test/test_db_api.rb.
|
72
71
|
|
73
|
-
=
|
72
|
+
= GridFS
|
74
73
|
|
75
|
-
The GridStore class
|
76
|
-
|
77
|
-
details, and see examples/gridfs.rb for code that uses many of the GridStore
|
78
|
-
features (metadata, content type, rewind/seek/tell, etc).
|
74
|
+
Note: The GridStore class has been deprecated. Use either the Grid or GridFileSystem
|
75
|
+
classes to take advantage of GridFS.
|
79
76
|
|
80
|
-
|
81
|
-
|
77
|
+
The Ruby driver include two abstractions for storing large files: Grid and GridFileSystem.
|
78
|
+
The Grid class is a Ruby implementation of MongoDB's GridFS file storage
|
79
|
+
specification. GridFileSystem is essentailly the same, but provides a more filesystem-like API
|
80
|
+
and assumes that filenames are unique.
|
82
81
|
|
83
|
-
|
82
|
+
An instance of both classes represents an individual file store. See the API reference
|
83
|
+
for details, and see examples/gridfs.rb for code that uses many of the Grid
|
84
|
+
features (metadata, content type, seek, tell, etc).
|
84
85
|
|
85
|
-
|
86
|
+
Examples:
|
87
|
+
include Mongo
|
88
|
+
|
89
|
+
# Get a database
|
90
|
+
db = Mongo::Connection.new.db('app-db')
|
86
91
|
|
87
|
-
# Store the text "Hello, world!" in the
|
88
|
-
|
89
|
-
|
92
|
+
# GridFileSystem. Store the text "Hello, world!" in the fs.
|
93
|
+
fs = GridFileSystem.new(db)
|
94
|
+
fs.open('filename', 'w') do |f|
|
95
|
+
f.write "Hello, world!"
|
90
96
|
end
|
91
97
|
|
92
|
-
# Output "Hello, world!"
|
93
|
-
|
98
|
+
# GridFileSystem. Output "Hello, world!"
|
99
|
+
fs = GridFileSystem.new(db)
|
100
|
+
fs.open('filename', 'r') do |f|
|
94
101
|
puts f.read
|
95
102
|
end
|
96
103
|
|
97
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
104
|
+
# Write a file on disk to the Grid
|
105
|
+
file = File.open('image.jpg')
|
106
|
+
grid = Grid.new(db)
|
107
|
+
id = grid.put(file)
|
101
108
|
|
102
|
-
# Retrieve
|
103
|
-
|
104
|
-
|
105
|
-
end
|
109
|
+
# Retrieve the file
|
110
|
+
file = grid.get(id)
|
111
|
+
file.read
|
106
112
|
|
113
|
+
# Get all the file's metata
|
114
|
+
file.filename
|
115
|
+
file.content_type
|
116
|
+
file.metadata
|
107
117
|
|
108
118
|
= Notes
|
109
119
|
|
@@ -294,8 +304,7 @@ It's also possible to test replica pairs with connection pooling:
|
|
294
304
|
|
295
305
|
===Shoulda and Mocha
|
296
306
|
|
297
|
-
|
298
|
-
follows:
|
307
|
+
Running the test suite requires shoulda and mocha. You can install them as follows:
|
299
308
|
|
300
309
|
$ gem install shoulda
|
301
310
|
$ gem install mocha
|
@@ -305,23 +314,6 @@ can override the default host (localhost) and port (Connection::DEFAULT_PORT) by
|
|
305
314
|
using the environment variables MONGO_RUBY_DRIVER_HOST and
|
306
315
|
MONGO_RUBY_DRIVER_PORT.
|
307
316
|
|
308
|
-
The project mongo-qa (http://github.com/mongodb/mongo-qa) contains many more
|
309
|
-
Mongo driver tests that are language independent. To run thoses tests as part
|
310
|
-
of the "rake test" task, download the code "next to" this directory. So, after
|
311
|
-
installing the mongo-qa code you would have these two directories next to each
|
312
|
-
other:
|
313
|
-
|
314
|
-
$ ls
|
315
|
-
mongo-qa
|
316
|
-
mongo-ruby-driver
|
317
|
-
$ rake test
|
318
|
-
|
319
|
-
The tests run just fine if the mongo-qa directory is not there.
|
320
|
-
|
321
|
-
Additionally, the script bin/validate is used by the mongo-qa project's
|
322
|
-
validator script.
|
323
|
-
|
324
|
-
|
325
317
|
= Documentation
|
326
318
|
|
327
319
|
This documentation is available online at http://api.mongodb.org/ruby. You can
|
@@ -342,7 +334,7 @@ See CREDITS.
|
|
342
334
|
|
343
335
|
= License
|
344
336
|
|
345
|
-
Copyright 2008-
|
337
|
+
Copyright 2008-2010 10gen Inc.
|
346
338
|
|
347
339
|
Licensed under the Apache License, Version 2.0 (the "License");
|
348
340
|
you may not use this file except in compliance with the License.
|
@@ -355,4 +347,3 @@ See CREDITS.
|
|
355
347
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
356
348
|
See the License for the specific language governing permissions and
|
357
349
|
limitations under the License.
|
358
|
-
|
data/Rakefile
CHANGED
@@ -47,7 +47,7 @@ namespace :test do
|
|
47
47
|
end
|
48
48
|
|
49
49
|
Rake::TestTask.new(:functional) do |t|
|
50
|
-
t.test_files = FileList['test
|
50
|
+
t.test_files = FileList['test/*_test.rb']
|
51
51
|
t.verbose = true
|
52
52
|
end
|
53
53
|
|
@@ -76,6 +76,16 @@ namespace :test do
|
|
76
76
|
t.verbose = true
|
77
77
|
end
|
78
78
|
|
79
|
+
Rake::TestTask.new(:auto_reconnect) do |t|
|
80
|
+
t.test_files = FileList['test/auxillary/autoreconnect_test.rb']
|
81
|
+
t.verbose = true
|
82
|
+
end
|
83
|
+
|
84
|
+
Rake::TestTask.new(:authentication) do |t|
|
85
|
+
t.test_files = FileList['test/auxillary/authentication_test.rb']
|
86
|
+
t.verbose = true
|
87
|
+
end
|
88
|
+
|
79
89
|
task :drop_databases do |t|
|
80
90
|
puts "Dropping test database..."
|
81
91
|
require File.join(File.dirname(__FILE__), 'lib', 'mongo')
|
@@ -96,10 +106,10 @@ end
|
|
96
106
|
|
97
107
|
desc "Generate YARD documentation"
|
98
108
|
task :ydoc do
|
99
|
-
|
100
|
-
out = File.join('ydoc',
|
109
|
+
require File.join(File.dirname(__FILE__), 'lib', 'mongo')
|
110
|
+
out = File.join('ydoc', Mongo::VERSION)
|
101
111
|
FileUtils.rm_rf('ydoc')
|
102
|
-
system "yardoc lib/**/*.rb lib/mongo/**/*.rb -o #{out} --title MongoRuby-#{
|
112
|
+
system "yardoc lib/**/*.rb lib/mongo/**/*.rb -e docs/yard_ext.rb -p docs/templates -o #{out} --title MongoRuby-#{Mongo::VERSION}"
|
103
113
|
end
|
104
114
|
|
105
115
|
desc "Publish documentation to mongo.rubyforge.org"
|
data/examples/gridfs.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
def assert
|
3
|
+
raise "Failed!" unless yield
|
4
|
+
end
|
2
5
|
|
3
6
|
require 'mongo'
|
4
|
-
require 'mongo/gridfs'
|
5
|
-
|
6
7
|
include Mongo
|
7
|
-
include GridFS
|
8
8
|
|
9
9
|
host = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
|
10
10
|
port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
|
@@ -12,77 +12,32 @@ port = ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT
|
|
12
12
|
puts "Connecting to #{host}:#{port}"
|
13
13
|
db = Connection.new(host, port).db('ruby-mongo-examples')
|
14
14
|
|
15
|
-
|
16
|
-
GridStore.open(db, fname, 'r') { |f| puts f.read }
|
17
|
-
end
|
18
|
-
|
19
|
-
# Write a new file
|
20
|
-
GridStore.open(db, 'foobar', 'w') { |f| f.write("hello, world!") }
|
21
|
-
|
22
|
-
# Read it and print out the contents
|
23
|
-
dump(db, 'foobar')
|
24
|
-
|
25
|
-
# Append more data
|
26
|
-
GridStore.open(db, 'foobar', 'w+') { |f| f.write("\n"); f.puts "line two" }
|
27
|
-
dump(db, 'foobar')
|
15
|
+
data = "hello, world!"
|
28
16
|
|
29
|
-
|
30
|
-
GridStore.open(db, 'foobar', 'w') { |f| f.puts "hello, sailor!" }
|
31
|
-
dump(db, 'foobar')
|
17
|
+
grid = Grid.new(db)
|
32
18
|
|
33
|
-
#
|
34
|
-
|
35
|
-
puts "File 'does-not-exist' exists: #{GridStore.exist?(db, 'does-not-exist')}"
|
19
|
+
# Write a new file. data can be a string or an io object responding to #read.
|
20
|
+
id = grid.put(data, 'hello.txt')
|
36
21
|
|
37
|
-
# Read
|
38
|
-
|
22
|
+
# Read it and print out the contents
|
23
|
+
file = grid.get(id)
|
24
|
+
puts file.read
|
39
25
|
|
40
|
-
#
|
41
|
-
|
42
|
-
f.write "hello, world!"
|
43
|
-
f.rewind
|
44
|
-
f.write "xyzzz"
|
45
|
-
puts f.tell # => 5
|
46
|
-
f.seek(4)
|
47
|
-
f.write('y')
|
48
|
-
}
|
49
|
-
dump(db, 'foobar') # => 'xyzzy'
|
26
|
+
# Delete the file
|
27
|
+
grid.delete(id)
|
50
28
|
|
51
|
-
|
52
|
-
|
53
|
-
|
29
|
+
begin
|
30
|
+
grid.get(id)
|
31
|
+
rescue => e
|
32
|
+
assert {e.class == Mongo::GridError}
|
33
|
+
end
|
54
34
|
|
55
35
|
# Metadata
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
# Add some metadata; change content type
|
65
|
-
GridStore.open(db, 'foobar', 'w+') { |f|
|
66
|
-
f.content_type = 'text/xml'
|
67
|
-
f.metadata = {'a' => 1}
|
68
|
-
}
|
69
|
-
# Print it
|
70
|
-
GridStore.open(db, 'foobar', 'r') { |f|
|
71
|
-
puts f.content_type
|
72
|
-
puts f.upload_date
|
73
|
-
puts f.chunk_size
|
74
|
-
puts f.metadata.inspect
|
75
|
-
}
|
76
|
-
|
77
|
-
# You can also set metadata when initially writing the file. Setting :root
|
78
|
-
# means that the file and its chunks are stored in a different root
|
79
|
-
# collection: instead of gridfs.files and gridfs.chunks, here we use
|
80
|
-
# my_files.files and my_files.chunks.
|
81
|
-
GridStore.open(db, 'foobar', 'w',
|
82
|
-
:content_type => 'text/plain',
|
83
|
-
:metadata => {'a' => 1},
|
84
|
-
:chunk_size => 1024 * 4,
|
85
|
-
:root => 'my_files') { |f|
|
86
|
-
f.puts 'hello, world'
|
87
|
-
}
|
88
|
-
|
36
|
+
id = grid.put(data, 'hello.txt', :content_type => 'text/plain', :metadata => {'name' => 'hello'})
|
37
|
+
file = grid.get(id)
|
38
|
+
|
39
|
+
p file.content_type
|
40
|
+
p file.metadata.inspect
|
41
|
+
p file.chunk_size
|
42
|
+
p file.file_length
|
43
|
+
p file.data
|
data/lib/mongo.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
2
|
|
3
3
|
module Mongo
|
4
|
-
VERSION = "0.
|
4
|
+
VERSION = "0.19"
|
5
5
|
end
|
6
6
|
|
7
7
|
begin
|
@@ -52,10 +52,12 @@ require 'mongo/util/conversions'
|
|
52
52
|
require 'mongo/util/server_version'
|
53
53
|
require 'mongo/util/bson_ruby'
|
54
54
|
|
55
|
-
require 'mongo/admin'
|
56
55
|
require 'mongo/collection'
|
57
56
|
require 'mongo/connection'
|
58
57
|
require 'mongo/cursor'
|
59
58
|
require 'mongo/db'
|
60
59
|
require 'mongo/exceptions'
|
61
60
|
require 'mongo/gridfs'
|
61
|
+
require 'mongo/gridfs/grid'
|
62
|
+
require 'mongo/gridfs/grid_io'
|
63
|
+
require 'mongo/gridfs/grid_file_system'
|
data/lib/mongo/collection.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# --
|
2
|
-
# Copyright (C) 2008-
|
2
|
+
# Copyright (C) 2008-2010 10gen Inc.
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -33,6 +33,8 @@ module Mongo
|
|
33
33
|
# if collection name is not a string or symbol
|
34
34
|
#
|
35
35
|
# @return [Collection]
|
36
|
+
#
|
37
|
+
# @core collections constructor_details
|
36
38
|
def initialize(db, name, pk_factory=nil)
|
37
39
|
case name
|
38
40
|
when Symbol, String
|
@@ -126,6 +128,8 @@ module Mongo
|
|
126
128
|
#
|
127
129
|
# @raise [RuntimeError]
|
128
130
|
# if given unknown options
|
131
|
+
#
|
132
|
+
# @core find find-instance_method
|
129
133
|
def find(selector={}, opts={})
|
130
134
|
fields = opts.delete(:fields)
|
131
135
|
fields = ["_id"] if fields && fields.empty?
|
@@ -221,6 +225,8 @@ module Mongo
|
|
221
225
|
# If true, check that the save succeeded. OperationFailure
|
222
226
|
# will be raised on an error. Note that a safe check requires an extra
|
223
227
|
# round-trip to the database.
|
228
|
+
#
|
229
|
+
# @core insert insert-instance_method
|
224
230
|
def insert(doc_or_docs, options={})
|
225
231
|
doc_or_docs = [doc_or_docs] unless doc_or_docs.is_a?(Array)
|
226
232
|
doc_or_docs.collect! { |doc| @pk_factory.create_pk(doc) }
|
@@ -248,15 +254,17 @@ module Mongo
|
|
248
254
|
#
|
249
255
|
# @raise [Mongo::OperationFailure] an exception will be raised iff safe mode is enabled
|
250
256
|
# and the operation fails.
|
257
|
+
#
|
258
|
+
# @core remove remove-instance_method
|
251
259
|
def remove(selector={}, opts={})
|
252
260
|
# Initial byte is 0.
|
253
261
|
message = ByteBuffer.new([0, 0, 0, 0])
|
254
262
|
BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{@name}")
|
255
263
|
message.put_int(0)
|
256
|
-
message.put_array(BSON.serialize(selector, false).to_a)
|
264
|
+
message.put_array(BSON.serialize(selector, false, true).to_a)
|
257
265
|
|
258
266
|
if opts[:safe]
|
259
|
-
@connection.send_message_with_safe_check(Mongo::Constants::OP_DELETE, message,
|
267
|
+
@connection.send_message_with_safe_check(Mongo::Constants::OP_DELETE, message, @db.name,
|
260
268
|
"db.#{@db.name}.remove(#{selector.inspect})")
|
261
269
|
# the return value of send_message_with_safe_check isn't actually meaningful --
|
262
270
|
# only the fact that it didn't raise an error is -- so just return true
|
@@ -285,6 +293,8 @@ module Mongo
|
|
285
293
|
# If true, check that the save succeeded. OperationFailure
|
286
294
|
# will be raised on an error. Note that a safe check requires an extra
|
287
295
|
# round-trip to the database.
|
296
|
+
#
|
297
|
+
# @core update update-instance_method
|
288
298
|
def update(selector, document, options={})
|
289
299
|
# Initial byte is 0.
|
290
300
|
message = ByteBuffer.new([0, 0, 0, 0])
|
@@ -293,8 +303,8 @@ module Mongo
|
|
293
303
|
update_options += 1 if options[:upsert]
|
294
304
|
update_options += 2 if options[:multi]
|
295
305
|
message.put_int(update_options)
|
296
|
-
message.put_array(BSON.serialize(selector, false).to_a)
|
297
|
-
message.put_array(BSON.serialize(document, false).to_a)
|
306
|
+
message.put_array(BSON.serialize(selector, false, true).to_a)
|
307
|
+
message.put_array(BSON.serialize(document, false, true).to_a)
|
298
308
|
if options[:safe]
|
299
309
|
@connection.send_message_with_safe_check(Mongo::Constants::OP_UPDATE, message, @db.name,
|
300
310
|
"db.#{@name}.update(#{selector.inspect}, #{document.inspect})")
|
@@ -313,6 +323,8 @@ module Mongo
|
|
313
323
|
# @param [Boolean] unique if true, this index will enforce a uniqueness constraint.
|
314
324
|
#
|
315
325
|
# @return [String] the name of the index created.
|
326
|
+
#
|
327
|
+
# @core indexes create_index-instance_method
|
316
328
|
def create_index(field_or_spec, unique=false)
|
317
329
|
field_h = OrderedHash.new
|
318
330
|
if field_or_spec.is_a?(String) || field_or_spec.is_a?(Symbol)
|
@@ -326,18 +338,26 @@ module Mongo
|
|
326
338
|
:ns => "#{@db.name}.#{@name}",
|
327
339
|
:key => field_h,
|
328
340
|
:unique => unique }
|
329
|
-
|
341
|
+
begin
|
342
|
+
insert_documents([sel], Mongo::DB::SYSTEM_INDEX_COLLECTION, false, true)
|
343
|
+
rescue Mongo::OperationFailure
|
344
|
+
raise Mongo::OperationFailure, "Failed to create index #{sel.inspect}."
|
345
|
+
end
|
330
346
|
name
|
331
347
|
end
|
332
348
|
|
333
349
|
# Drop a specified index.
|
334
350
|
#
|
335
351
|
# @param [String] name
|
352
|
+
#
|
353
|
+
# @core indexes
|
336
354
|
def drop_index(name)
|
337
355
|
@db.drop_index(@name, name)
|
338
356
|
end
|
339
357
|
|
340
358
|
# Drop all indexes.
|
359
|
+
#
|
360
|
+
# @core indexes
|
341
361
|
def drop_indexes
|
342
362
|
|
343
363
|
# Note: calling drop_indexes with no args will drop them all.
|
@@ -369,6 +389,8 @@ module Mongo
|
|
369
389
|
# @return [Collection] a collection containing the results of the operation.
|
370
390
|
#
|
371
391
|
# @see http://www.mongodb.org/display/DOCS/MapReduce Offical MongoDB map/reduce documentation.
|
392
|
+
#
|
393
|
+
# @core mapreduce map_reduce-instance_method
|
372
394
|
def map_reduce(map, reduce, opts={})
|
373
395
|
map = Code.new(map) unless map.is_a?(Code)
|
374
396
|
reduce = Code.new(reduce) unless reduce.is_a?(Code)
|
@@ -397,100 +419,57 @@ module Mongo
|
|
397
419
|
# @param [String, Code] finalize :: optional. a JavaScript function that receives and modifies
|
398
420
|
# each of the resultant grouped objects. Available only when group is run
|
399
421
|
# with command set to true.
|
400
|
-
# @param [
|
401
|
-
#
|
422
|
+
# @param [Nil] deprecated this param in a placeholder for a deprecated param. It will be removed
|
423
|
+
# in the next release.
|
402
424
|
#
|
403
425
|
# @return [Array] the grouped items.
|
404
|
-
def group(key, condition, initial, reduce,
|
426
|
+
def group(key, condition, initial, reduce, finalize=nil, deprecated=nil)
|
405
427
|
|
406
|
-
|
428
|
+
# Warn of changed API post eval deprecation.
|
429
|
+
if finalize == true || finalize == false || deprecated
|
430
|
+
warn "The API for Collection#group has changed. 'Finalize' is now the fifth parameter, " +
|
431
|
+
"since it's no longer necessary to specify whether #group is run as a command. " +
|
432
|
+
"See http://api.mongodb.org/ruby/current/Mongo/Collection.html#group-instance_method for details."
|
433
|
+
end
|
407
434
|
|
408
|
-
|
435
|
+
reduce = Code.new(reduce) unless reduce.is_a?(Code)
|
409
436
|
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
}
|
437
|
+
group_command = {
|
438
|
+
"group" => {
|
439
|
+
"ns" => @name,
|
440
|
+
"$reduce" => reduce,
|
441
|
+
"cond" => condition,
|
442
|
+
"initial" => initial
|
417
443
|
}
|
444
|
+
}
|
418
445
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
else
|
425
|
-
key_type = "$keyf"
|
426
|
-
key_value = key.is_a?(Code) ? key : Code.new(key)
|
427
|
-
end
|
428
|
-
|
429
|
-
group_command["group"][key_type] = key_value
|
430
|
-
end
|
431
|
-
|
432
|
-
# only add finalize if specified
|
433
|
-
if finalize
|
434
|
-
finalize = Code.new(finalize) unless finalize.is_a?(Code)
|
435
|
-
group_command['group']['finalize'] = finalize
|
436
|
-
end
|
437
|
-
|
438
|
-
result = @db.command group_command
|
439
|
-
|
440
|
-
if result["ok"] == 1
|
441
|
-
return result["retval"]
|
446
|
+
unless key.nil?
|
447
|
+
if key.is_a? Array
|
448
|
+
key_type = "key"
|
449
|
+
key_value = {}
|
450
|
+
key.each { |k| key_value[k] = 1 }
|
442
451
|
else
|
443
|
-
|
452
|
+
key_type = "$keyf"
|
453
|
+
key_value = key.is_a?(Code) ? key : Code.new(key)
|
444
454
|
end
|
445
455
|
|
446
|
-
|
447
|
-
|
448
|
-
warn "Collection#group must now be run as a command; you can do this by passing 'true' as the command argument."
|
449
|
-
|
450
|
-
raise OperationFailure, ":finalize can be specified only when " +
|
451
|
-
"group is run as a command (set command param to true)" if finalize
|
456
|
+
group_command["group"][key_type] = key_value
|
457
|
+
end
|
452
458
|
|
453
|
-
|
454
|
-
|
459
|
+
# only add finalize if specified
|
460
|
+
# check to see if users have sent the finalizer as the last argument.
|
461
|
+
finalize = deprecated if deprecated.is_a?(String) || deprecated.is_a?(Code)
|
462
|
+
finalize = Code.new(finalize) if finalize.is_a?(String)
|
463
|
+
if finalize.is_a?(Code)
|
464
|
+
group_command['group']['finalize'] = finalize
|
465
|
+
end
|
455
466
|
|
456
|
-
|
457
|
-
when Code
|
458
|
-
scope = reduce.scope
|
459
|
-
else
|
460
|
-
scope = {}
|
461
|
-
end
|
462
|
-
scope.merge!({
|
463
|
-
"ns" => @name,
|
464
|
-
"keys" => key,
|
465
|
-
"condition" => condition,
|
466
|
-
"initial" => initial })
|
467
|
-
|
468
|
-
group_function = <<EOS
|
469
|
-
function () {
|
470
|
-
var c = db[ns].find(condition);
|
471
|
-
var map = new Map();
|
472
|
-
var reduce_function = #{reduce};
|
473
|
-
while (c.hasNext()) {
|
474
|
-
var obj = c.next();
|
475
|
-
|
476
|
-
var key = {};
|
477
|
-
for (var i = 0; i < keys.length; i++) {
|
478
|
-
var k = keys[i];
|
479
|
-
key[k] = obj[k];
|
480
|
-
}
|
467
|
+
result = @db.command group_command
|
481
468
|
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
map.put(key, aggObj);
|
487
|
-
}
|
488
|
-
reduce_function(obj, aggObj);
|
489
|
-
}
|
490
|
-
return {"result": map.values()};
|
491
|
-
}
|
492
|
-
EOS
|
493
|
-
@db.eval(Code.new(group_function, scope))["result"]
|
469
|
+
if result["ok"] == 1
|
470
|
+
result["retval"]
|
471
|
+
else
|
472
|
+
raise OperationFailure, "group command failed: #{result['errmsg']}"
|
494
473
|
end
|
495
474
|
end
|
496
475
|
|
@@ -534,7 +513,7 @@ EOS
|
|
534
513
|
# Note: If operating in auth mode, the client must be authorized as an admin to
|
535
514
|
# perform this operation.
|
536
515
|
#
|
537
|
-
# @param [String
|
516
|
+
# @param [String] new_name the new name for this collection
|
538
517
|
#
|
539
518
|
# @raise [InvalidName] if +new_name+ is an invalid collection name.
|
540
519
|
def rename(new_name)
|
@@ -562,6 +541,8 @@ EOS
|
|
562
541
|
# Get information on the indexes for this collection.
|
563
542
|
#
|
564
543
|
# @return [Hash] a hash where the keys are index names.
|
544
|
+
#
|
545
|
+
# @core indexes
|
565
546
|
def index_information
|
566
547
|
@db.index_information(@name)
|
567
548
|
end
|
@@ -609,7 +590,7 @@ EOS
|
|
609
590
|
# Initial byte is 0.
|
610
591
|
message = ByteBuffer.new([0, 0, 0, 0])
|
611
592
|
BSON_RUBY.serialize_cstr(message, "#{@db.name}.#{collection_name}")
|
612
|
-
documents.each { |doc| message.put_array(BSON.serialize(doc, check_keys).to_a) }
|
593
|
+
documents.each { |doc| message.put_array(BSON.serialize(doc, check_keys, true).to_a) }
|
613
594
|
if safe
|
614
595
|
@connection.send_message_with_safe_check(Mongo::Constants::OP_INSERT, message, @db.name,
|
615
596
|
"db.#{collection_name}.insert(#{documents.inspect})")
|