jmongo 1.0.3 → 1.1.0
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/Gemfile +8 -0
- data/Gemfile.lock +43 -0
- data/Rakefile +72 -0
- data/jmongo.gemspec +84 -6
- data/lib/jmongo.rb +6 -14
- data/lib/jmongo/collection.rb +196 -114
- data/lib/jmongo/connection.rb +39 -13
- data/lib/jmongo/cursor.rb +161 -63
- data/lib/jmongo/db.rb +119 -30
- data/lib/jmongo/exceptions.rb +39 -0
- data/lib/jmongo/mongo-2.6.5.gb1.jar +0 -0
- data/lib/jmongo/mongo/bson.rb +130 -0
- data/lib/jmongo/mongo/collection.rb +185 -0
- data/lib/jmongo/mongo/connection.rb +45 -0
- data/lib/jmongo/mongo/db.rb +31 -0
- data/lib/jmongo/mongo/jmongo.rb +44 -0
- data/lib/jmongo/mongo/mongo.rb +98 -0
- data/lib/jmongo/mongo/ruby_ext.rb +38 -0
- data/lib/jmongo/mongo/utils.rb +136 -0
- data/lib/jmongo/version.rb +1 -1
- data/test-results.txt +98 -0
- data/test/auxillary/1.4_features.rb +166 -0
- data/test/auxillary/authentication_test.rb +68 -0
- data/test/auxillary/autoreconnect_test.rb +41 -0
- data/test/auxillary/fork_test.rb +30 -0
- data/test/auxillary/repl_set_auth_test.rb +58 -0
- data/test/auxillary/slave_connection_test.rb +36 -0
- data/test/auxillary/threaded_authentication_test.rb +101 -0
- data/test/bson/binary_test.rb +15 -0
- data/test/bson/bson_test.rb +657 -0
- data/test/bson/byte_buffer_test.rb +208 -0
- data/test/bson/hash_with_indifferent_access_test.rb +38 -0
- data/test/bson/json_test.rb +17 -0
- data/test/bson/object_id_test.rb +138 -0
- data/test/bson/ordered_hash_test.rb +245 -0
- data/test/bson/test_helper.rb +46 -0
- data/test/bson/timestamp_test.rb +46 -0
- data/test/collection_test.rb +933 -0
- data/test/connection_test.rb +325 -0
- data/test/conversions_test.rb +121 -0
- data/test/cursor_fail_test.rb +75 -0
- data/test/cursor_message_test.rb +43 -0
- data/test/cursor_test.rb +547 -0
- data/test/data/empty_data +0 -0
- data/test/data/sample_data +0 -0
- data/test/data/sample_file.pdf +0 -0
- data/test/data/small_data.txt +1 -0
- data/test/db_api_test.rb +739 -0
- data/test/db_connection_test.rb +15 -0
- data/test/db_test.rb +325 -0
- data/test/grid_file_system_test.rb +260 -0
- data/test/grid_io_test.rb +210 -0
- data/test/grid_test.rb +259 -0
- data/test/load/thin/config.ru +6 -0
- data/test/load/thin/config.yml.template +6 -0
- data/test/load/thin/load.rb +24 -0
- data/test/load/unicorn/config.ru +6 -0
- data/test/load/unicorn/load.rb +23 -0
- data/test/load/unicorn/unicorn.rb.template +29 -0
- data/test/replica_sets/connect_test.rb +111 -0
- data/test/replica_sets/connection_string_test.rb +29 -0
- data/test/replica_sets/count_test.rb +36 -0
- data/test/replica_sets/insert_test.rb +54 -0
- data/test/replica_sets/pooled_insert_test.rb +58 -0
- data/test/replica_sets/query_secondaries.rb +109 -0
- data/test/replica_sets/query_test.rb +52 -0
- data/test/replica_sets/read_preference_test.rb +43 -0
- data/test/replica_sets/refresh_test.rb +123 -0
- data/test/replica_sets/replication_ack_test.rb +71 -0
- data/test/replica_sets/rs_test_helper.rb +27 -0
- data/test/safe_test.rb +68 -0
- data/test/support/hash_with_indifferent_access.rb +186 -0
- data/test/support/keys.rb +45 -0
- data/test/support_test.rb +19 -0
- data/test/test_helper.rb +111 -0
- data/test/threading/threading_with_large_pool_test.rb +90 -0
- data/test/threading_test.rb +88 -0
- data/test/tools/auth_repl_set_manager.rb +14 -0
- data/test/tools/keyfile.txt +1 -0
- data/test/tools/repl_set_manager.rb +377 -0
- data/test/unit/collection_test.rb +128 -0
- data/test/unit/connection_test.rb +85 -0
- data/test/unit/cursor_test.rb +127 -0
- data/test/unit/db_test.rb +96 -0
- data/test/unit/grid_test.rb +51 -0
- data/test/unit/node_test.rb +73 -0
- data/test/unit/pool_manager_test.rb +47 -0
- data/test/unit/pool_test.rb +9 -0
- data/test/unit/read_test.rb +101 -0
- data/test/unit/safe_test.rb +125 -0
- data/test/uri_test.rb +92 -0
- metadata +170 -99
- data/lib/jmongo/ajrb.rb +0 -189
- data/lib/jmongo/jmongo_jext.rb +0 -302
- data/lib/jmongo/mongo-2.6.3.jar +0 -0
- data/lib/jmongo/utils.rb +0 -61
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
jmongo (1.0.3)
|
5
|
+
require_all (~> 1.2)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
awesome_print (0.4.0)
|
11
|
+
diff-lcs (1.1.3)
|
12
|
+
fuubar (0.0.6)
|
13
|
+
rspec (~> 2.0)
|
14
|
+
rspec-instafail (~> 0.1.8)
|
15
|
+
ruby-progressbar (~> 0.0.10)
|
16
|
+
metaclass (0.0.1)
|
17
|
+
mocha (0.10.0)
|
18
|
+
metaclass (~> 0.0.1)
|
19
|
+
rake (0.9.2)
|
20
|
+
require_all (1.2.0)
|
21
|
+
rspec (2.6.0)
|
22
|
+
rspec-core (~> 2.6.0)
|
23
|
+
rspec-expectations (~> 2.6.0)
|
24
|
+
rspec-mocks (~> 2.6.0)
|
25
|
+
rspec-core (2.6.4)
|
26
|
+
rspec-expectations (2.6.0)
|
27
|
+
diff-lcs (~> 1.1.2)
|
28
|
+
rspec-instafail (0.1.8)
|
29
|
+
rspec-mocks (2.6.0)
|
30
|
+
ruby-progressbar (0.0.10)
|
31
|
+
shoulda (2.11.3)
|
32
|
+
|
33
|
+
PLATFORMS
|
34
|
+
java
|
35
|
+
|
36
|
+
DEPENDENCIES
|
37
|
+
awesome_print (~> 0.4)
|
38
|
+
fuubar (~> 0.0)
|
39
|
+
jmongo!
|
40
|
+
mocha
|
41
|
+
rake
|
42
|
+
rspec (~> 2.6)
|
43
|
+
shoulda
|
data/Rakefile
CHANGED
@@ -116,3 +116,75 @@ task :validate do
|
|
116
116
|
exit!
|
117
117
|
end
|
118
118
|
end
|
119
|
+
|
120
|
+
require 'rake/testtask'
|
121
|
+
|
122
|
+
task :test do
|
123
|
+
puts "\nTo test the pure jruby driver: \nrake test:jruby\n\n"
|
124
|
+
end
|
125
|
+
|
126
|
+
namespace :test do
|
127
|
+
|
128
|
+
desc "Test the driver using pure jruby (no C extension)"
|
129
|
+
task :jruby do
|
130
|
+
ENV['C_EXT'] = nil
|
131
|
+
if ENV['TEST']
|
132
|
+
Rake::Task['test:functional'].invoke
|
133
|
+
else
|
134
|
+
Rake::Task['test:unit'].invoke
|
135
|
+
Rake::Task['test:functional'].invoke
|
136
|
+
Rake::Task['test:bson'].invoke
|
137
|
+
Rake::Task['test:pooled_threading'].invoke
|
138
|
+
Rake::Task['test:drop_databases'].invoke
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
desc "Run the replica set test suite"
|
143
|
+
Rake::TestTask.new(:rs) do |t|
|
144
|
+
t.test_files = FileList['test/replica_sets/*_test.rb']
|
145
|
+
t.verbose = true
|
146
|
+
t.ruby_opts << '-w'
|
147
|
+
end
|
148
|
+
|
149
|
+
Rake::TestTask.new(:unit) do |t|
|
150
|
+
t.test_files = FileList['test/unit/*_test.rb']
|
151
|
+
t.verbose = true
|
152
|
+
t.ruby_opts << '-w'
|
153
|
+
end
|
154
|
+
|
155
|
+
Rake::TestTask.new(:functional) do |t|
|
156
|
+
t.test_files = FileList['test/*_test.rb']
|
157
|
+
t.verbose = true
|
158
|
+
t.ruby_opts << '-w'
|
159
|
+
end
|
160
|
+
|
161
|
+
Rake::TestTask.new(:pooled_threading) do |t|
|
162
|
+
t.test_files = FileList['test/threading/*_test.rb']
|
163
|
+
t.verbose = true
|
164
|
+
t.ruby_opts << '-w'
|
165
|
+
end
|
166
|
+
|
167
|
+
Rake::TestTask.new(:auto_reconnect) do |t|
|
168
|
+
t.test_files = FileList['test/auxillary/autoreconnect_test.rb']
|
169
|
+
t.verbose = true
|
170
|
+
t.ruby_opts << '-w'
|
171
|
+
end
|
172
|
+
|
173
|
+
Rake::TestTask.new(:authentication) do |t|
|
174
|
+
t.test_files = FileList['test/auxillary/authentication_test.rb']
|
175
|
+
t.verbose = true
|
176
|
+
t.ruby_opts << '-w'
|
177
|
+
end
|
178
|
+
|
179
|
+
Rake::TestTask.new(:new_features) do |t|
|
180
|
+
t.test_files = FileList['test/auxillary/1.4_features.rb']
|
181
|
+
t.verbose = true
|
182
|
+
t.ruby_opts << '-w'
|
183
|
+
end
|
184
|
+
|
185
|
+
Rake::TestTask.new(:bson) do |t|
|
186
|
+
t.test_files = FileList['test/bson/*_test.rb']
|
187
|
+
t.verbose = true
|
188
|
+
t.ruby_opts << '-w'
|
189
|
+
end
|
190
|
+
end
|
data/jmongo.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'jmongo'
|
3
|
-
s.version = '1.0
|
4
|
-
s.date = '2011-
|
3
|
+
s.version = '1.1.0'
|
4
|
+
s.date = '2011-10-03'
|
5
5
|
s.platform = Gem::Platform::RUBY
|
6
6
|
s.authors = ["Chuck Remes","Guy Boertje", "Lee Henson"]
|
7
7
|
s.email = ["cremes@mac.com", "guyboertje@gmail.com", "lee.m.henson@gmail.com"]
|
@@ -11,6 +11,8 @@ Gem::Specification.new do |s|
|
|
11
11
|
|
12
12
|
# = MANIFEST =
|
13
13
|
s.files = %w[
|
14
|
+
Gemfile
|
15
|
+
Gemfile.lock
|
14
16
|
History.txt
|
15
17
|
LICENSE.txt
|
16
18
|
README.txt
|
@@ -18,18 +20,94 @@ Gem::Specification.new do |s|
|
|
18
20
|
bin/jmongo
|
19
21
|
jmongo.gemspec
|
20
22
|
lib/jmongo.rb
|
21
|
-
lib/jmongo/ajrb.rb
|
22
23
|
lib/jmongo/collection.rb
|
23
24
|
lib/jmongo/connection.rb
|
24
25
|
lib/jmongo/cursor.rb
|
25
26
|
lib/jmongo/db.rb
|
26
27
|
lib/jmongo/exceptions.rb
|
27
|
-
lib/jmongo/
|
28
|
-
lib/jmongo/mongo
|
29
|
-
lib/jmongo/
|
28
|
+
lib/jmongo/mongo-2.6.5.gb1.jar
|
29
|
+
lib/jmongo/mongo/bson.rb
|
30
|
+
lib/jmongo/mongo/collection.rb
|
31
|
+
lib/jmongo/mongo/connection.rb
|
32
|
+
lib/jmongo/mongo/db.rb
|
33
|
+
lib/jmongo/mongo/jmongo.rb
|
34
|
+
lib/jmongo/mongo/mongo.rb
|
35
|
+
lib/jmongo/mongo/ruby_ext.rb
|
36
|
+
lib/jmongo/mongo/utils.rb
|
30
37
|
lib/jmongo/version.rb
|
31
38
|
spec/jmongo_spec.rb
|
32
39
|
spec/spec_helper.rb
|
40
|
+
test-results.txt
|
41
|
+
test/auxillary/1.4_features.rb
|
42
|
+
test/auxillary/authentication_test.rb
|
43
|
+
test/auxillary/autoreconnect_test.rb
|
44
|
+
test/auxillary/fork_test.rb
|
45
|
+
test/auxillary/repl_set_auth_test.rb
|
46
|
+
test/auxillary/slave_connection_test.rb
|
47
|
+
test/auxillary/threaded_authentication_test.rb
|
48
|
+
test/bson/binary_test.rb
|
49
|
+
test/bson/bson_test.rb
|
50
|
+
test/bson/byte_buffer_test.rb
|
51
|
+
test/bson/hash_with_indifferent_access_test.rb
|
52
|
+
test/bson/json_test.rb
|
53
|
+
test/bson/object_id_test.rb
|
54
|
+
test/bson/ordered_hash_test.rb
|
55
|
+
test/bson/test_helper.rb
|
56
|
+
test/bson/timestamp_test.rb
|
57
|
+
test/collection_test.rb
|
58
|
+
test/connection_test.rb
|
59
|
+
test/conversions_test.rb
|
60
|
+
test/cursor_fail_test.rb
|
61
|
+
test/cursor_message_test.rb
|
62
|
+
test/cursor_test.rb
|
63
|
+
test/data/empty_data
|
64
|
+
test/data/sample_data
|
65
|
+
test/data/sample_file.pdf
|
66
|
+
test/data/small_data.txt
|
67
|
+
test/db_api_test.rb
|
68
|
+
test/db_connection_test.rb
|
69
|
+
test/db_test.rb
|
70
|
+
test/grid_file_system_test.rb
|
71
|
+
test/grid_io_test.rb
|
72
|
+
test/grid_test.rb
|
73
|
+
test/load/thin/config.ru
|
74
|
+
test/load/thin/config.yml.template
|
75
|
+
test/load/thin/load.rb
|
76
|
+
test/load/unicorn/config.ru
|
77
|
+
test/load/unicorn/load.rb
|
78
|
+
test/load/unicorn/unicorn.rb.template
|
79
|
+
test/replica_sets/connect_test.rb
|
80
|
+
test/replica_sets/connection_string_test.rb
|
81
|
+
test/replica_sets/count_test.rb
|
82
|
+
test/replica_sets/insert_test.rb
|
83
|
+
test/replica_sets/pooled_insert_test.rb
|
84
|
+
test/replica_sets/query_secondaries.rb
|
85
|
+
test/replica_sets/query_test.rb
|
86
|
+
test/replica_sets/read_preference_test.rb
|
87
|
+
test/replica_sets/refresh_test.rb
|
88
|
+
test/replica_sets/replication_ack_test.rb
|
89
|
+
test/replica_sets/rs_test_helper.rb
|
90
|
+
test/safe_test.rb
|
91
|
+
test/support/hash_with_indifferent_access.rb
|
92
|
+
test/support/keys.rb
|
93
|
+
test/support_test.rb
|
94
|
+
test/test_helper.rb
|
95
|
+
test/threading/threading_with_large_pool_test.rb
|
96
|
+
test/threading_test.rb
|
97
|
+
test/tools/auth_repl_set_manager.rb
|
98
|
+
test/tools/keyfile.txt
|
99
|
+
test/tools/repl_set_manager.rb
|
100
|
+
test/unit/collection_test.rb
|
101
|
+
test/unit/connection_test.rb
|
102
|
+
test/unit/cursor_test.rb
|
103
|
+
test/unit/db_test.rb
|
104
|
+
test/unit/grid_test.rb
|
105
|
+
test/unit/node_test.rb
|
106
|
+
test/unit/pool_manager_test.rb
|
107
|
+
test/unit/pool_test.rb
|
108
|
+
test/unit/read_test.rb
|
109
|
+
test/unit/safe_test.rb
|
110
|
+
test/uri_test.rb
|
33
111
|
]
|
34
112
|
# = MANIFEST =
|
35
113
|
|
data/lib/jmongo.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
# Copyright (C) 2010 Chuck Remes
|
1
|
+
# Copyright (C) 2010 Chuck Remes, Guy Boertje
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in
|
4
|
+
# you may not use this file except in coSmpliance with the License.
|
5
5
|
# You may obtain a copy of the License at
|
6
6
|
#
|
7
7
|
# http://www.apache.org/licenses/LICENSE-2.0
|
@@ -17,19 +17,11 @@ unless RUBY_PLATFORM =~ /java/
|
|
17
17
|
exit 255
|
18
18
|
end
|
19
19
|
|
20
|
+
require 'timeout'
|
21
|
+
require 'java'
|
22
|
+
|
20
23
|
require 'require_all'
|
21
24
|
require_rel 'jmongo/*.jar'
|
22
25
|
|
23
|
-
|
24
|
-
require 'jmongo/jmongo_jext'
|
25
|
-
require_rel 'jmongo/*.rb'
|
26
|
-
|
27
|
-
module Mongo
|
28
|
-
ASCENDING = 1
|
29
|
-
DESCENDING = -1
|
30
|
-
GEO2D = '2d'
|
26
|
+
require_rel 'jmongo/**/*.rb'
|
31
27
|
|
32
|
-
module Constants
|
33
|
-
DEFAULT_BATCH_SIZE = 100
|
34
|
-
end
|
35
|
-
end
|
data/lib/jmongo/collection.rb
CHANGED
@@ -35,30 +35,31 @@ module Mongo
|
|
35
35
|
# @return [Collection]
|
36
36
|
#
|
37
37
|
# @core collections constructor_details
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
#db, name, options=nil, j_collection=nil
|
39
|
+
def initialize(*args)
|
40
|
+
j_collection = nil
|
41
|
+
@opts = {}
|
42
|
+
if args.size == 4
|
43
|
+
j_collection = args.pop
|
43
44
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
if name.empty? or name.include? ".."
|
48
|
-
raise Mongo::InvalidNSName, "collection names cannot be empty"
|
45
|
+
if args.size == 3
|
46
|
+
@opts = args.pop
|
49
47
|
end
|
50
|
-
if
|
51
|
-
raise
|
48
|
+
if args.size < 2
|
49
|
+
raise ArgumentError.new("Must supply at least name and db parameters")
|
52
50
|
end
|
53
|
-
if
|
54
|
-
|
51
|
+
if args.first.respond_to?('collection_names')
|
52
|
+
db, name = args
|
53
|
+
else
|
54
|
+
name, db = args
|
55
55
|
end
|
56
56
|
|
57
|
-
@
|
57
|
+
@name = validate_name(name)
|
58
|
+
@db, @j_db = db, db.j_db
|
58
59
|
@connection = @db.connection
|
59
|
-
@pk_factory =
|
60
|
+
@pk_factory = @opts[:pk] || BSON::ObjectId
|
60
61
|
@hint = nil
|
61
|
-
@j_collection = @j_db.
|
62
|
+
@j_collection = j_collection || @j_db.get_collection(@name)
|
62
63
|
end
|
63
64
|
|
64
65
|
# Return a sub-collection of this collection by name. If 'users' is a collection, then
|
@@ -73,8 +74,14 @@ module Mongo
|
|
73
74
|
# @return [Collection]
|
74
75
|
# the specified sub-collection
|
75
76
|
def [](name)
|
77
|
+
new_name = "#{self.name}.#{name}"
|
78
|
+
validate_name new_name
|
79
|
+
@db.create_collection(new_name, @opts)
|
76
80
|
end
|
77
81
|
|
82
|
+
def capped?
|
83
|
+
@j_collection.isCapped
|
84
|
+
end
|
78
85
|
# Set a hint field for query optimizer. Hint may be a single field
|
79
86
|
# name, array of field names, or a hash (preferably an [OrderedHash]).
|
80
87
|
# If using MongoDB > 1.1, you probably don't ever need to set a hint.
|
@@ -131,29 +138,34 @@ module Mongo
|
|
131
138
|
#
|
132
139
|
# @core find find-instance_method
|
133
140
|
def find(selector={}, opts={})
|
134
|
-
fields = opts.delete(:fields)
|
135
|
-
fields = ["_id"] if fields && fields.empty?
|
141
|
+
fields = prep_fields(opts.delete(:fields))
|
136
142
|
skip = opts.delete(:skip) || skip || 0
|
137
143
|
limit = opts.delete(:limit) || 0
|
138
144
|
sort = opts.delete(:sort)
|
139
145
|
hint = opts.delete(:hint)
|
140
146
|
snapshot = opts.delete(:snapshot)
|
141
147
|
batch_size = opts.delete(:batch_size)
|
142
|
-
|
148
|
+
timeout = (opts.delete(:timeout) == false) ? false : true
|
149
|
+
transformer = opts.delete(:transformer)
|
150
|
+
if timeout == false && !block_given?
|
143
151
|
raise ArgumentError, "Timeout can be set to false only when #find is invoked with a block."
|
144
152
|
end
|
145
|
-
|
153
|
+
|
146
154
|
if hint
|
147
155
|
hint = normalize_hint_fields(hint)
|
148
156
|
else
|
149
157
|
hint = @hint # assumed to be normalized already
|
150
158
|
end
|
159
|
+
|
151
160
|
raise RuntimeError, "Unknown options [#{opts.inspect}]" unless opts.empty?
|
152
161
|
|
153
162
|
cursor = Cursor.new(self, :selector => selector, :fields => fields, :skip => skip, :limit => limit,
|
154
|
-
|
163
|
+
:order => sort, :hint => hint, :snapshot => snapshot,
|
164
|
+
:batch_size => batch_size, :timeout => timeout,
|
165
|
+
:transformer => transformer)
|
155
166
|
if block_given?
|
156
167
|
yield cursor
|
168
|
+
cursor.close
|
157
169
|
nil
|
158
170
|
else
|
159
171
|
cursor
|
@@ -186,7 +198,11 @@ module Mongo
|
|
186
198
|
else
|
187
199
|
raise TypeError, "spec_or_object_id must be an instance of ObjectId or Hash, or nil"
|
188
200
|
end
|
189
|
-
|
201
|
+
begin
|
202
|
+
find_one_document(spec, opts)
|
203
|
+
rescue => ex
|
204
|
+
raise OperationFailure, ex.message
|
205
|
+
end
|
190
206
|
end
|
191
207
|
|
192
208
|
# Save a document to this collection.
|
@@ -225,8 +241,9 @@ module Mongo
|
|
225
241
|
doc_or_docs = [doc_or_docs] unless doc_or_docs.kind_of?(Array)
|
226
242
|
doc_or_docs.collect! { |doc| @pk_factory.create_pk(doc) }
|
227
243
|
safe = (options[:safe] || false)
|
228
|
-
|
229
|
-
|
244
|
+
continue = (options[:continue_on_error] || false)
|
245
|
+
docs = insert_documents(doc_or_docs, safe, continue)
|
246
|
+
docs.size == 1 ? docs.first['_id'] : docs.collect{|doc| doc['_id']}
|
230
247
|
end
|
231
248
|
alias_method :<<, :insert
|
232
249
|
|
@@ -279,7 +296,7 @@ module Mongo
|
|
279
296
|
def update(selector, document, options={})
|
280
297
|
upsert, multi = !!(options[:upsert]), !!(options[:multi])
|
281
298
|
safe = (options[:safe] || false)
|
282
|
-
update_documents(selector, document,upsert,multi,safe)
|
299
|
+
update_documents(selector, document, upsert, multi, safe)
|
283
300
|
end
|
284
301
|
|
285
302
|
# Create a new index.
|
@@ -325,17 +342,21 @@ module Mongo
|
|
325
342
|
#
|
326
343
|
# @core indexes create_index-instance_method
|
327
344
|
def create_index(spec, opts={})
|
328
|
-
|
345
|
+
_create_indexes(spec, opts)
|
329
346
|
end
|
330
347
|
alias_method :ensure_index, :create_index
|
331
348
|
|
332
349
|
# Drop a specified index.
|
333
350
|
#
|
334
|
-
# @param [String]
|
351
|
+
# @param [String, Array] spec
|
352
|
+
# should be either a single field name or an array of
|
353
|
+
# [field name, direction] pairs. Directions should be specified
|
354
|
+
# as Mongo::ASCENDING, Mongo::DESCENDING, or Mongo::GEO2D.
|
335
355
|
#
|
336
356
|
# @core indexes
|
337
|
-
def drop_index(
|
338
|
-
|
357
|
+
def drop_index(spec)
|
358
|
+
raise MongoArgumentError, "Cannot drop index for nil name" unless name
|
359
|
+
_drop_index(spec)
|
339
360
|
end
|
340
361
|
|
341
362
|
# Drop all indexes.
|
@@ -369,12 +390,14 @@ module Mongo
|
|
369
390
|
def find_and_modify(opts={})
|
370
391
|
query = opts[:query] || {}
|
371
392
|
fields = opts[:fields] || {}
|
372
|
-
sort = opts[:sort] ||
|
393
|
+
sort = prep_sort(opts[:sort] || [])
|
373
394
|
update = opts[:update] || {}
|
374
395
|
remove = opts[:remove] || false
|
375
396
|
new_ = opts[:new] || false
|
376
397
|
upsert = opts[:upsert] || false
|
377
|
-
|
398
|
+
trap_raise(OperationFailure) do
|
399
|
+
find_and_modify_document(query, fields, sort, remove, update, new_, upsert)
|
400
|
+
end
|
378
401
|
end
|
379
402
|
|
380
403
|
# Perform a map/reduce operation on the current collection.
|
@@ -399,72 +422,125 @@ module Mongo
|
|
399
422
|
#
|
400
423
|
# @core mapreduce map_reduce-instance_method
|
401
424
|
def map_reduce(map, reduce, opts={})
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
425
|
+
query = opts.fetch(:query,{})
|
426
|
+
sort = opts.fetch(:sort,[])
|
427
|
+
limit = opts.fetch(:limit,0)
|
428
|
+
finalize = opts[:finalize]
|
429
|
+
out = opts[:out]
|
430
|
+
keeptemp = opts.fetch(:keeptemp,true)
|
431
|
+
verbose = opts.fetch(:verbose,true)
|
432
|
+
raw = opts.delete(:raw)
|
433
|
+
|
434
|
+
m = map.to_s
|
435
|
+
r = reduce.to_s
|
436
|
+
|
437
|
+
mrc = case out
|
438
|
+
when String
|
439
|
+
JMongo::MapReduceCommand.new(@j_collection, m, r, out, REPLACE, to_dbobject(query))
|
440
|
+
when Hash
|
441
|
+
if out.keys.size != 1
|
442
|
+
raise ArgumentError, "You need to specify one key value pair in the out hash"
|
443
|
+
end
|
444
|
+
out_type = out.keys.first
|
445
|
+
out_val = out[out_type]
|
446
|
+
unless MapReduceEnumHash.keys.include?(out_type)
|
447
|
+
raise ArgumentError, "Your out hash must have one of these keys: #{MapReduceEnumHash.keys}"
|
448
|
+
end
|
449
|
+
out_type_enum = MapReduceEnumHash[out_type]
|
450
|
+
out_dest = out_val.is_a?(String) ? out_val : nil
|
451
|
+
JMongo::MapReduceCommand.new(@j_collection, m, r, out_dest, out_type_enum, to_dbobject(query))
|
452
|
+
else
|
453
|
+
raise ArgumentError, "You need to specify an out parameter in the options hash"
|
454
|
+
end
|
455
|
+
|
456
|
+
mrc.verbose = verbose
|
457
|
+
mrc.sort = prep_sort(sort)
|
458
|
+
mrc.limit = limit
|
459
|
+
mrc.finalize = finalize
|
460
|
+
result = from_dbobject(@j_db.command(mrc.toDBObject))
|
461
|
+
|
462
|
+
if raw
|
463
|
+
result
|
464
|
+
elsif result["result"]
|
465
|
+
@db[result["result"]]
|
466
|
+
else
|
467
|
+
raise ArgumentError, "Could not instantiate collection from result. If you specified " +
|
468
|
+
"{:out => {:inline => true}}, then you must also specify :raw => true to get the results."
|
414
469
|
end
|
415
|
-
@db[result["result"]]
|
416
470
|
end
|
417
471
|
alias :mapreduce :map_reduce
|
418
472
|
|
419
473
|
# Perform a group aggregation.
|
420
474
|
#
|
421
|
-
# @param [
|
422
|
-
#
|
423
|
-
#
|
424
|
-
# @
|
425
|
-
# @
|
426
|
-
# @
|
427
|
-
#
|
428
|
-
#
|
429
|
-
#
|
430
|
-
# @
|
431
|
-
|
432
|
-
|
475
|
+
# @param [Hash] opts the options for this group operation. The minimum required are :initial
|
476
|
+
# and :reduce.
|
477
|
+
#
|
478
|
+
# @option opts [Array, String, Symbol] :key (nil) Either the name of a field or a list of fields to group by (optional).
|
479
|
+
# @option opts [String, BSON::Code] :keyf (nil) A JavaScript function to be used to generate the grouping keys (optional).
|
480
|
+
# @option opts [String, BSON::Code] :cond ({}) A document specifying a query for filtering the documents over
|
481
|
+
# which the aggregation is run (optional).
|
482
|
+
# @option opts [Hash] :initial the initial value of the aggregation counter object (required).
|
483
|
+
# @option opts [String, BSON::Code] :reduce (nil) a JavaScript aggregation function (required).
|
484
|
+
# @option opts [String, BSON::Code] :finalize (nil) a JavaScript function that receives and modifies
|
485
|
+
# each of the resultant grouped objects. Available only when group is run with command
|
486
|
+
# set to true.
|
487
|
+
#
|
488
|
+
# @return [Array] the command response consisting of grouped items.
|
489
|
+
def group(opts, condition={}, initial={}, reduce=nil, finalize=nil)
|
490
|
+
key = keyf = false
|
491
|
+
if opts.is_a?(Hash)
|
492
|
+
reduce, finalize, initial= opts.values_at(:reduce, :finalize, :initial)
|
493
|
+
key, keyf = opts.values_at(:key, :keyf)
|
494
|
+
condition = opts.fetch(:cond, {})
|
495
|
+
unless key.nil? && keyf.nil?
|
496
|
+
unless key.is_a?(Array) || keyf.is_a?(String) || keyf.is_a?(BSON::Code)
|
497
|
+
raise MongoArgumentError, "Group takes either an array of fields to group by or a JavaScript function" +
|
498
|
+
"in the form of a String or BSON::Code."
|
499
|
+
end
|
500
|
+
end
|
501
|
+
else
|
502
|
+
warn "Collection#group no longer take a list of parameters. This usage is deprecated and will be remove in v2.0." +
|
503
|
+
"Check out the new API at http://api.mongodb.org/ruby/current/Mongo/Collection.html#group-instance_method"
|
504
|
+
case opts
|
505
|
+
when Array
|
506
|
+
key = opts
|
507
|
+
when String, BSON::Code
|
508
|
+
keyf = opts
|
509
|
+
else
|
510
|
+
raise MongoArgumentError, "Group takes either an array of fields to group by or a JavaScript function" +
|
511
|
+
"in the form of a String or BSON::Code."
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
if !(reduce && initial)
|
516
|
+
raise MongoArgumentError, "Group requires at minimum values for initial and reduce."
|
517
|
+
end
|
433
518
|
|
434
|
-
|
519
|
+
cmd = {
|
435
520
|
"group" => {
|
436
521
|
"ns" => @name,
|
437
|
-
"$reduce" => reduce,
|
522
|
+
"$reduce" => reduce.to_bson_code,
|
438
523
|
"cond" => condition,
|
439
524
|
"initial" => initial
|
440
525
|
}
|
441
526
|
}
|
442
527
|
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
else
|
449
|
-
key_type = "$keyf"
|
450
|
-
key_value = key.is_a?(BSON::Code) ? key : BSON::Code.new(key)
|
451
|
-
end
|
452
|
-
|
453
|
-
group_command["group"][key_type] = key_value
|
528
|
+
if keyf
|
529
|
+
cmd["group"]["$keyf"] = keyf.to_bson_code
|
530
|
+
elsif key
|
531
|
+
key_hash = Hash[key.zip( [1]*key.size )]
|
532
|
+
cmd["group"]["key"] = key_hash
|
454
533
|
end
|
455
534
|
|
456
|
-
|
457
|
-
|
458
|
-
group_command['group']['finalize'] = finalize
|
535
|
+
if finalize
|
536
|
+
cmd['group']['finalize'] = finalize.to_bson_code
|
459
537
|
end
|
460
538
|
|
461
|
-
result = @db.command
|
539
|
+
result = from_dbobject(@db.command(cmd))
|
462
540
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
raise OperationFailure, "group command failed: #{result['errmsg']}"
|
467
|
-
end
|
541
|
+
return result["retval"] if Mongo.result_ok?(result)
|
542
|
+
|
543
|
+
raise OperationFailure, "group command failed: #{result['errmsg']}"
|
468
544
|
end
|
469
545
|
|
470
546
|
# Return a list of distinct values for +key+ across all
|
@@ -494,12 +570,11 @@ module Mongo
|
|
494
570
|
# @return [Array] an array of distinct values.
|
495
571
|
def distinct(key, query=nil)
|
496
572
|
raise MongoArgumentError unless [String, Symbol].include?(key.class)
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
@db.command(command)["values"]
|
573
|
+
if query
|
574
|
+
from_dbobject @j_collection.distinct(key.to_s, to_dbobject(query))
|
575
|
+
else
|
576
|
+
from_dbobject @j_collection.distinct(key.to_s)
|
577
|
+
end
|
503
578
|
end
|
504
579
|
|
505
580
|
# Rename this collection.
|
@@ -511,25 +586,14 @@ module Mongo
|
|
511
586
|
#
|
512
587
|
# @raise [Mongo::InvalidNSName] if +new_name+ is an invalid collection name.
|
513
588
|
def rename(new_name)
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
589
|
+
name = validate_name(new_name)
|
590
|
+
begin
|
591
|
+
jcol = @j_collection.rename(name)
|
592
|
+
@name = name
|
593
|
+
@j_collection = jcol
|
594
|
+
rescue => ex
|
595
|
+
raise MongoDBError, "Error renaming collection: #{name}, more: #{ex.message}"
|
518
596
|
end
|
519
|
-
|
520
|
-
new_name = new_name.to_s
|
521
|
-
|
522
|
-
if new_name.empty? or new_name.include? ".."
|
523
|
-
raise Mongo::InvalidNSName, "collection names cannot be empty"
|
524
|
-
end
|
525
|
-
if new_name.include? "$"
|
526
|
-
raise Mongo::InvalidNSName, "collection names must not contain '$'"
|
527
|
-
end
|
528
|
-
if new_name.match(/^\./) or new_name.match(/\.$/)
|
529
|
-
raise Mongo::InvalidNSName, "collection names must not start or end with '.'"
|
530
|
-
end
|
531
|
-
|
532
|
-
@db.rename_collection(@name, new_name)
|
533
597
|
end
|
534
598
|
|
535
599
|
# Get information on the indexes for this collection.
|
@@ -546,7 +610,9 @@ module Mongo
|
|
546
610
|
#
|
547
611
|
# @return [Hash] options that apply to this collection.
|
548
612
|
def options
|
549
|
-
@db.collections_info(@name).
|
613
|
+
info = @db.collections_info(@name).to_a
|
614
|
+
ap info
|
615
|
+
info.last['options']
|
550
616
|
end
|
551
617
|
|
552
618
|
# Return stats on the collection. Uses MongoDB's collstats command.
|
@@ -559,14 +625,36 @@ module Mongo
|
|
559
625
|
# Get the number of documents in this collection.
|
560
626
|
#
|
561
627
|
# @return [Integer]
|
562
|
-
def count
|
563
|
-
@j_collection.count()
|
628
|
+
def count(opts={})
|
629
|
+
return @j_collection.count() if opts.empty?
|
630
|
+
query = opts[:query] || opts['query'] || {}
|
631
|
+
fields = opts[:fields] || opts['fields'] || {}
|
632
|
+
limit = opts[:limit] || opts['limit'] || 0
|
633
|
+
skip = opts[:skip] || opts['skip'] || 0
|
634
|
+
@j_collection.get_count(to_dbobject(query), to_dbobject(fields), limit, skip)
|
564
635
|
end
|
565
636
|
|
566
637
|
alias :size :count
|
567
638
|
|
568
639
|
protected
|
569
640
|
|
641
|
+
def validate_name(new_name)
|
642
|
+
raise TypeError, "new_name must be a string like" unless new_name.respond_to?(:to_s)
|
643
|
+
|
644
|
+
name = new_name.to_s
|
645
|
+
|
646
|
+
if name.empty? || name.include?("..")
|
647
|
+
raise Mongo::InvalidNSName, "collection names cannot be empty"
|
648
|
+
end
|
649
|
+
if name.include? "$"
|
650
|
+
raise Mongo::InvalidNSName, "collection names must not contain '$'" unless name =~ /((^\$cmd)|(oplog\.\$main))/
|
651
|
+
end
|
652
|
+
if name.match(/^\./) || name.match(/\.$/)
|
653
|
+
raise Mongo::InvalidNSName, "collection names must not start or end with '.'"
|
654
|
+
end
|
655
|
+
name
|
656
|
+
end
|
657
|
+
|
570
658
|
def normalize_hint_fields(hint)
|
571
659
|
case hint
|
572
660
|
when String
|
@@ -576,16 +664,10 @@ module Mongo
|
|
576
664
|
when nil
|
577
665
|
nil
|
578
666
|
else
|
579
|
-
h = OrderedHash.new
|
580
|
-
hint.to_a.each { |k| h[k] = 1 }
|
667
|
+
h = BSON::OrderedHash.new
|
668
|
+
hint.to_a.each { |k| h[k.to_s] = 1 }
|
581
669
|
h
|
582
670
|
end
|
583
671
|
end
|
584
|
-
|
585
|
-
private
|
586
|
-
|
587
|
-
def generate_index_name(spec)
|
588
|
-
@j_collection.genIndexName(to_dbobject(spec))
|
589
|
-
end
|
590
672
|
end
|
591
673
|
end
|