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
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'bson')
|
2
|
+
require 'rubygems' if RUBY_VERSION < '1.9.0' && ENV['C_EXT']
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
def silently
|
6
|
+
warn_level = $VERBOSE
|
7
|
+
$VERBOSE = nil
|
8
|
+
result = yield
|
9
|
+
$VERBOSE = warn_level
|
10
|
+
result
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
require 'rubygems' if RUBY_VERSION < "1.9.0" && !ENV['C_EXT']
|
15
|
+
silently { require 'shoulda' }
|
16
|
+
silently { require 'mocha' }
|
17
|
+
rescue LoadError
|
18
|
+
puts <<MSG
|
19
|
+
|
20
|
+
This test suite requires shoulda and mocha.
|
21
|
+
You can install them as follows:
|
22
|
+
gem install shoulda
|
23
|
+
gem install mocha
|
24
|
+
|
25
|
+
MSG
|
26
|
+
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'bson_ext/cbson' if !(RUBY_PLATFORM =~ /java/) && ENV['C_EXT']
|
31
|
+
|
32
|
+
class Test::Unit::TestCase
|
33
|
+
include BSON
|
34
|
+
|
35
|
+
def assert_raise_error(klass, message)
|
36
|
+
begin
|
37
|
+
yield
|
38
|
+
rescue => e
|
39
|
+
assert_equal klass, e.class
|
40
|
+
assert e.message.include?(message), "#{e.message} does not include #{message}."
|
41
|
+
else
|
42
|
+
flunk "Expected assertion #{klass} but none was raised."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require './test/bson/test_helper'
|
2
|
+
|
3
|
+
class TimestampTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_timestamp_equality
|
6
|
+
t1 = Timestamp.new(5000, 200)
|
7
|
+
t2 = Timestamp.new(5000, 200)
|
8
|
+
assert_equal t2, t1
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_timestamp_range
|
12
|
+
t = 1;
|
13
|
+
while(t < 1_000_000_000 ) do
|
14
|
+
ts = Timestamp.new(t, 0)
|
15
|
+
doc = {:ts => ts}
|
16
|
+
bson = BSON::BSON_CODER.serialize(doc)
|
17
|
+
assert_equal doc[:ts], BSON::BSON_CODER.deserialize(bson)['ts']
|
18
|
+
t = t * 10
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_timestamp_32bit_compatibility
|
23
|
+
max_32bit_fixnum = (1 << 30) - 1
|
24
|
+
test_val = max_32bit_fixnum + 10
|
25
|
+
|
26
|
+
ts = Timestamp.new(test_val, test_val)
|
27
|
+
doc = {:ts => ts}
|
28
|
+
bson = BSON::BSON_CODER.serialize(doc)
|
29
|
+
assert_equal doc[:ts], BSON::BSON_CODER.deserialize(bson)['ts']
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_implements_array_for_backward_compatibility
|
33
|
+
silently do
|
34
|
+
ts = Timestamp.new(5000, 200)
|
35
|
+
assert_equal 200, ts[0]
|
36
|
+
assert_equal 5000, ts[1]
|
37
|
+
|
38
|
+
array = ts.map {|t| t }
|
39
|
+
assert_equal 2, array.length
|
40
|
+
|
41
|
+
assert_equal 200, array[0]
|
42
|
+
assert_equal 5000, array[1]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,933 @@
|
|
1
|
+
require './test/test_helper'
|
2
|
+
|
3
|
+
CONNECTION ||= Mongo::Connection.new(TEST_HOST, TEST_PORT, :op_timeout => 10)
|
4
|
+
$db = CONNECTION.db(MONGO_TEST_DB)
|
5
|
+
|
6
|
+
VERSION = CONNECTION.server_version
|
7
|
+
apr VERSION
|
8
|
+
|
9
|
+
def clear_collections
|
10
|
+
$db.collection_names.each do |n|
|
11
|
+
$db.drop_collection(n) unless n =~ /system/
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
clear_collections
|
16
|
+
|
17
|
+
$test = $db.collection("test")
|
18
|
+
|
19
|
+
class TestCollection < MiniTest::Unit::TestCase
|
20
|
+
|
21
|
+
def setup
|
22
|
+
clear_collections
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_capped_method
|
26
|
+
$db.drop_collection('normal')
|
27
|
+
|
28
|
+
$db.create_collection('normal')
|
29
|
+
assert !$db['normal'].capped?
|
30
|
+
$db.drop_collection('normal')
|
31
|
+
|
32
|
+
$db.create_collection('c', :capped => true, :size => 100_000)
|
33
|
+
assert $db['c'].capped?
|
34
|
+
$db.drop_collection('c')
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_optional_pk_factory
|
38
|
+
@coll_default_pk = $db.collection('stuff')
|
39
|
+
assert_equal BSON::ObjectId, @coll_default_pk.pk_factory
|
40
|
+
@coll_default_pk = $db.create_collection('more-stuff')
|
41
|
+
assert_equal BSON::ObjectId, @coll_default_pk.pk_factory
|
42
|
+
|
43
|
+
# Create a db with a pk_factory.
|
44
|
+
@db = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
|
45
|
+
ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT).db(MONGO_TEST_DB, :pk => Object.new)
|
46
|
+
@coll = @db.collection('coll-with-pk')
|
47
|
+
assert @coll.pk_factory.is_a?(Object)
|
48
|
+
|
49
|
+
@coll = @db.create_collection('created_coll_with_pk')
|
50
|
+
assert @coll.pk_factory.is_a?(Object)
|
51
|
+
end
|
52
|
+
|
53
|
+
class TestPK
|
54
|
+
def self.create_pk
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_pk_factory_on_collection
|
59
|
+
@coll2 = Collection.new('foo', $db, :pk => TestPK)
|
60
|
+
assert_equal TestPK, @coll2.pk_factory
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_valid_names
|
64
|
+
assert_raises Mongo::InvalidNSName do
|
65
|
+
$db["te$t"]
|
66
|
+
end
|
67
|
+
|
68
|
+
assert_raises Mongo::InvalidNSName do
|
69
|
+
$db['$main']
|
70
|
+
end
|
71
|
+
|
72
|
+
assert $db['$cmd']
|
73
|
+
assert $db['oplog.$main']
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_collection
|
77
|
+
assert_kind_of Collection, $db["test"]
|
78
|
+
assert_equal $db["test"].name(), $db.collection("test").name()
|
79
|
+
assert_equal $db["test"].name(), $db[:test].name()
|
80
|
+
|
81
|
+
assert_kind_of Collection, $db["test"]["foo"]
|
82
|
+
assert_equal $db["test"]["foo"].name(), $db.collection("test.foo").name()
|
83
|
+
assert_equal $db["test"]["foo"].name(), $db["test.foo"].name()
|
84
|
+
|
85
|
+
$db["test"]["foo"].remove
|
86
|
+
$db["test"]["foo"].insert("x" => 5)
|
87
|
+
assert_equal 5, $db.collection("test.foo").find_one()["x"]
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_rename_collection
|
91
|
+
$db.drop_collection('foo1')
|
92
|
+
$db.drop_collection('bar1')
|
93
|
+
|
94
|
+
@col = $db.create_collection('foo1')
|
95
|
+
assert_equal 'foo1', @col.name
|
96
|
+
|
97
|
+
@col.rename('bar1')
|
98
|
+
assert_equal 'bar1', @col.name
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_nil_id
|
102
|
+
skip("The Java driver does not allow nil _id")
|
103
|
+
assert_equal 5, $test.insert({"_id" => 5, "foo" => "bar"}, {:safe => true})
|
104
|
+
assert_equal 5, $test.save({"_id" => 5, "foo" => "baz"}, {:safe => true})
|
105
|
+
assert_equal nil, $test.find_one("foo" => "bar")
|
106
|
+
assert_equal "baz", $test.find_one(:_id => 5)["foo"]
|
107
|
+
assert_raises OperationFailure do
|
108
|
+
$test.insert({"_id" => 5, "foo" => "bar"}, {:safe => true})
|
109
|
+
end
|
110
|
+
|
111
|
+
assert_equal nil, $test.insert({"_id" => nil, "foo" => "bar"}, {:safe => true})
|
112
|
+
assert_equal nil, $test.save({"_id" => nil, "foo" => "baz"}, {:safe => true})
|
113
|
+
assert_equal nil, $test.find_one("foo" => "bar")
|
114
|
+
assert_equal "baz", $test.find_one(:_id => nil)["foo"]
|
115
|
+
assert_raises OperationFailure do
|
116
|
+
$test.insert({"_id" => nil, "foo" => "bar"}, {:safe => true})
|
117
|
+
end
|
118
|
+
assert_raises OperationFailure do
|
119
|
+
$test.insert({:_id => nil, "foo" => "bar"}, {:safe => true})
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
if VERSION > "1.1"
|
124
|
+
def setup_for_distinct
|
125
|
+
$test.remove
|
126
|
+
$test.insert([{:a => 0, :b => {:c => "a"}},
|
127
|
+
{:a => 1, :b => {:c => "b"}},
|
128
|
+
{:a => 1, :b => {:c => "c"}},
|
129
|
+
{:a => 2, :b => {:c => "a"}},
|
130
|
+
{:a => 3},
|
131
|
+
{:a => 3}])
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_distinct_queries
|
135
|
+
setup_for_distinct
|
136
|
+
assert_equal [0, 1, 2, 3], $test.distinct(:a).sort
|
137
|
+
assert_equal ["a", "b", "c"], $test.distinct("b.c").sort
|
138
|
+
end
|
139
|
+
|
140
|
+
if VERSION >= "1.2"
|
141
|
+
def test_filter_collection_with_query
|
142
|
+
setup_for_distinct
|
143
|
+
assert_equal [2, 3], $test.distinct(:a, {:a => {"$gt" => 1}}).sort
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_filter_nested_objects
|
147
|
+
setup_for_distinct
|
148
|
+
assert_equal ["a", "b"], $test.distinct("b.c", {"b.c" => {"$ne" => "c"}}).sort
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_safe_insert
|
154
|
+
$test.create_index("hello", :unique => true)
|
155
|
+
a = {"hello" => "world"}
|
156
|
+
$test.insert(a)
|
157
|
+
$test.insert(a)
|
158
|
+
assert($db.get_last_error['err'].include?("11000"))
|
159
|
+
|
160
|
+
assert_raises OperationFailure do
|
161
|
+
$test.insert(a, :safe => true)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_bulk_insert_with_continue_on_error
|
166
|
+
if VERSION >= "2.0"
|
167
|
+
$test.create_index([["foo", 1]], :unique => true)
|
168
|
+
docs = []
|
169
|
+
docs << {:foo => 1}
|
170
|
+
docs << {:foo => 1}
|
171
|
+
docs << {:foo => 2}
|
172
|
+
docs << {:foo => 3}
|
173
|
+
assert_raises OperationFailure do
|
174
|
+
$test.insert(docs, :safe => true)
|
175
|
+
end
|
176
|
+
assert_equal 1, $test.count
|
177
|
+
$test.remove
|
178
|
+
|
179
|
+
docs = []
|
180
|
+
docs << {:foo => 1}
|
181
|
+
docs << {:foo => 1}
|
182
|
+
docs << {:foo => 2}
|
183
|
+
docs << {:foo => 3}
|
184
|
+
docs << {:foo => 3}
|
185
|
+
assert_raises OperationFailure do
|
186
|
+
$test.insert(docs, :safe => true, :continue_on_error => true)
|
187
|
+
end
|
188
|
+
assert_equal 3, $test.count
|
189
|
+
|
190
|
+
$test.remove
|
191
|
+
$test.drop_index("foo_1")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_maximum_insert_size
|
196
|
+
skip("The Java driver does not enforce a maximum")
|
197
|
+
docs = []
|
198
|
+
16.times do
|
199
|
+
docs << {'foo' => 'a' * 1_000_000}
|
200
|
+
end
|
201
|
+
|
202
|
+
assert_raises InvalidOperation do
|
203
|
+
$test.insert(docs)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_update
|
208
|
+
id1 = $test.save("x" => 5)
|
209
|
+
$test.update({}, {"$inc" => {"x" => 1}})
|
210
|
+
assert_equal 1, $test.count()
|
211
|
+
assert_equal 6, $test.find_one(:_id => id1)["x"]
|
212
|
+
|
213
|
+
id2 = $test.save("x" => 1)
|
214
|
+
$test.update({"x" => 6}, {"$inc" => {"x" => 1}})
|
215
|
+
assert_equal 7, $test.find_one(:_id => id1)["x"]
|
216
|
+
assert_equal 1, $test.find_one(:_id => id2)["x"]
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_multi_update
|
220
|
+
$test.save("num" => 10)
|
221
|
+
$test.save("num" => 10)
|
222
|
+
$test.save("num" => 10)
|
223
|
+
assert_equal 3, $test.count
|
224
|
+
|
225
|
+
$test.update({"num" => 10}, {"$set" => {"num" => 100}}, :multi => true)
|
226
|
+
$test.find.each do |doc|
|
227
|
+
assert_equal 100, doc["num"]
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_upsert
|
232
|
+
$test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
|
233
|
+
$test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
|
234
|
+
|
235
|
+
assert_equal 1, $test.count()
|
236
|
+
assert_equal 2, $test.find_one()["count"]
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_safe_update
|
240
|
+
$test.create_index("x", :unique => true)
|
241
|
+
$test.insert("x" => 5)
|
242
|
+
$test.insert("x" => 10)
|
243
|
+
|
244
|
+
# Can update an indexed collection.
|
245
|
+
$test.update({}, {"$inc" => {"x" => 1}})
|
246
|
+
assert !$db.error?
|
247
|
+
|
248
|
+
# Can't duplicate an index.
|
249
|
+
assert_raises OperationFailure do
|
250
|
+
$test.update({}, {"x" => 10}, :safe => true)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_safe_save
|
255
|
+
$test.create_index("hello", :unique => true)
|
256
|
+
|
257
|
+
$test.save("hello" => "world")
|
258
|
+
$test.save("hello" => "world")
|
259
|
+
|
260
|
+
assert_raises OperationFailure do
|
261
|
+
$test.save({"hello" => "world"}, :safe => true)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_safe_remove
|
266
|
+
@conn = standard_connection
|
267
|
+
@db = @conn[MONGO_TEST_DB]
|
268
|
+
@test = @db['test-safe-remove']
|
269
|
+
@test.save({:a => 50})
|
270
|
+
assert_equal 1, @test.remove({}, :safe => true)["n"]
|
271
|
+
@test.drop
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_remove_return_value
|
275
|
+
assert_equal true, $test.remove({})
|
276
|
+
end
|
277
|
+
|
278
|
+
def test_count
|
279
|
+
|
280
|
+
assert_equal 0, $test.count
|
281
|
+
$test.save(:x => 1)
|
282
|
+
$test.save(:x => 2)
|
283
|
+
assert_equal 2, $test.count
|
284
|
+
|
285
|
+
assert_equal 1, $test.count(:query => {:x => 1})
|
286
|
+
assert_equal 1, $test.count(:limit => 1)
|
287
|
+
assert_equal 0, $test.count(:skip => 2)
|
288
|
+
end
|
289
|
+
|
290
|
+
# Note: #size is just an alias for #count.
|
291
|
+
def test_size
|
292
|
+
assert_equal 0, $test.count
|
293
|
+
assert_equal $test.size, $test.count
|
294
|
+
$test.save("x" => 1)
|
295
|
+
$test.save("x" => 2)
|
296
|
+
assert_equal $test.size, $test.count
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_no_timeout_option
|
300
|
+
|
301
|
+
assert_raises ArgumentError, "Timeout can be set to false only when #find is invoked with a block." do
|
302
|
+
$test.find({}, :timeout => false)
|
303
|
+
end
|
304
|
+
|
305
|
+
$test.find({}, :timeout => false) do |cursor|
|
306
|
+
assert_equal 0, cursor.count
|
307
|
+
end
|
308
|
+
|
309
|
+
$test.save("x" => 1)
|
310
|
+
$test.save("x" => 2)
|
311
|
+
$test.find({}, :timeout => false) do |cursor|
|
312
|
+
assert_equal 2, cursor.count
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
def test_default_timeout
|
317
|
+
cursor = $test.find
|
318
|
+
assert_equal true, cursor.timeout
|
319
|
+
end
|
320
|
+
|
321
|
+
def test_fields_as_hash
|
322
|
+
$test.save(:a => 1, :b => 1, :c => 1)
|
323
|
+
|
324
|
+
doc = $test.find_one({:a => 1}, :fields => {:b => 0})
|
325
|
+
assert_nil doc['b']
|
326
|
+
assert doc['a']
|
327
|
+
assert doc['c']
|
328
|
+
|
329
|
+
doc = $test.find_one({:a => 1}, :fields => {:a => 1, :b => 1})
|
330
|
+
assert_nil doc['c']
|
331
|
+
assert doc['a']
|
332
|
+
assert doc['b']
|
333
|
+
|
334
|
+
|
335
|
+
assert_raises Mongo::OperationFailure do
|
336
|
+
$test.find_one({:a => 1}, :fields => {:a => 1, :b => 0})
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
if VERSION >= "1.5.1"
|
341
|
+
def test_fields_with_slice
|
342
|
+
$test.save({:foo => [1, 2, 3, 4, 5, 6], :test => 'slice'})
|
343
|
+
|
344
|
+
doc = $test.find_one({:test => 'slice'}, :fields => {'foo' => {'$slice' => [0, 3]}})
|
345
|
+
assert_equal [1, 2, 3], doc['foo']
|
346
|
+
$test.remove
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
def test_find_one
|
351
|
+
id = $test.save("hello" => "world", "foo" => "bar")
|
352
|
+
|
353
|
+
assert_equal "world", $test.find_one()["hello"]
|
354
|
+
assert_equal $test.find_one(id), $test.find_one()
|
355
|
+
assert_equal $test.find_one(nil), $test.find_one()
|
356
|
+
assert_equal $test.find_one({}), $test.find_one()
|
357
|
+
assert_equal $test.find_one("hello" => "world"), $test.find_one()
|
358
|
+
assert_equal $test.find_one(BSON::OrderedHash["hello", "world"]), $test.find_one()
|
359
|
+
|
360
|
+
assert $test.find_one(nil, :fields => ["hello"]).include?("hello")
|
361
|
+
assert !$test.find_one(nil, :fields => ["foo"]).include?("hello")
|
362
|
+
assert_equal ["_id"], $test.find_one(nil, :fields => []).keys()
|
363
|
+
|
364
|
+
assert_equal nil, $test.find_one("hello" => "foo")
|
365
|
+
assert_equal nil, $test.find_one(BSON::OrderedHash["hello", "foo"])
|
366
|
+
assert_equal nil, $test.find_one(ObjectId.new)
|
367
|
+
|
368
|
+
assert_raises TypeError do
|
369
|
+
$test.find_one(6)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
def test_insert_adds_id
|
374
|
+
doc = {"hello" => "world"}
|
375
|
+
$test.insert(doc)
|
376
|
+
assert(doc.include?(:_id))
|
377
|
+
|
378
|
+
docs = [{"hello" => "world"}, {"hello" => "world"}]
|
379
|
+
$test.insert(docs)
|
380
|
+
docs.each do |d|
|
381
|
+
assert(d.include?(:_id))
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
def test_save_adds_id
|
386
|
+
doc = {"hello" => "world"}
|
387
|
+
$test.save(doc)
|
388
|
+
assert(doc.include?(:_id))
|
389
|
+
end
|
390
|
+
|
391
|
+
def test_optional_find_block
|
392
|
+
10.times do |i|
|
393
|
+
$test.save("i" => i)
|
394
|
+
end
|
395
|
+
|
396
|
+
x = nil
|
397
|
+
$test.find("i" => 2) { |cursor|
|
398
|
+
x = cursor.count()
|
399
|
+
}
|
400
|
+
assert_equal 1, x
|
401
|
+
|
402
|
+
i = 0
|
403
|
+
$test.find({}, :skip => 5) do |cursor|
|
404
|
+
cursor.each do |doc|
|
405
|
+
i = i + 1
|
406
|
+
end
|
407
|
+
end
|
408
|
+
assert_equal 5, i
|
409
|
+
|
410
|
+
c = nil
|
411
|
+
$test.find() do |cursor|
|
412
|
+
c = cursor
|
413
|
+
end
|
414
|
+
assert c.closed?
|
415
|
+
end
|
416
|
+
|
417
|
+
def test_map_reduce
|
418
|
+
$test << { "user_id" => 1 }
|
419
|
+
$test << { "user_id" => 2 }
|
420
|
+
m = "function() { emit(this.user_id, 1); }"
|
421
|
+
r = "function(k,vals) { return 1; }"
|
422
|
+
res = $test.map_reduce(m, r, :out => 'foo');
|
423
|
+
assert res.find_one({"_id" => 1})
|
424
|
+
assert res.find_one({"_id" => 2})
|
425
|
+
end
|
426
|
+
|
427
|
+
def test_map_reduce_with_code_objects
|
428
|
+
$test << { "user_id" => 1 }
|
429
|
+
$test << { "user_id" => 2 }
|
430
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
431
|
+
r = Code.new("function(k,vals) { return 1; }")
|
432
|
+
res = $test.map_reduce(m, r, :out => 'foo');
|
433
|
+
assert res.find_one({"_id" => 1})
|
434
|
+
assert res.find_one({"_id" => 2})
|
435
|
+
end
|
436
|
+
|
437
|
+
def test_map_reduce_with_options
|
438
|
+
$test << { "user_id" => 1 }
|
439
|
+
$test << { "user_id" => 2 }
|
440
|
+
$test << { "user_id" => 3 }
|
441
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
442
|
+
r = Code.new("function(k,vals) { return 1; }")
|
443
|
+
res = $test.map_reduce(m, r, :query => {"user_id" => {"$gt" => 1}}, :out => 'foo');
|
444
|
+
assert_equal 2, res.count
|
445
|
+
assert res.find_one({"_id" => 2})
|
446
|
+
assert res.find_one({"_id" => 3})
|
447
|
+
end
|
448
|
+
|
449
|
+
def test_map_reduce_with_raw_response
|
450
|
+
$test << { "user_id" => 1 }
|
451
|
+
$test << { "user_id" => 2 }
|
452
|
+
$test << { "user_id" => 3 }
|
453
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
454
|
+
r = Code.new("function(k,vals) { return 1; }")
|
455
|
+
res = $test.map_reduce(m, r, :raw => true, :out => 'foo')
|
456
|
+
assert res["result"]
|
457
|
+
assert res["counts"]
|
458
|
+
assert res["timeMillis"]
|
459
|
+
end
|
460
|
+
|
461
|
+
def test_map_reduce_with_output_collection
|
462
|
+
$test << { "user_id" => 1 }
|
463
|
+
$test << { "user_id" => 2 }
|
464
|
+
$test << { "user_id" => 3 }
|
465
|
+
output_collection = "test-map-coll"
|
466
|
+
m = Code.new("function() { emit(this.user_id, 1); }")
|
467
|
+
r = Code.new("function(k,vals) { return 1; }")
|
468
|
+
res = $test.map_reduce(m, r, :raw => true, :out => output_collection)
|
469
|
+
assert_equal output_collection, res["result"]
|
470
|
+
assert res["counts"]
|
471
|
+
assert res["timeMillis"]
|
472
|
+
end
|
473
|
+
|
474
|
+
if VERSION >= "1.8.0"
|
475
|
+
def test_map_reduce_with_collection_merge
|
476
|
+
$test << {:user_id => 1}
|
477
|
+
$test << {:user_id => 2}
|
478
|
+
output_collection = "test-map-coll"
|
479
|
+
m = Code.new("function() { emit(this.user_id, {count: 1}); }")
|
480
|
+
r = Code.new("function(k,vals) { var sum = 0;" +
|
481
|
+
" vals.forEach(function(v) { sum += v.count;} ); return {count: sum}; }")
|
482
|
+
res = $test.map_reduce(m, r, :out => output_collection)
|
483
|
+
|
484
|
+
$test.remove
|
485
|
+
$test << {:user_id => 3}
|
486
|
+
res = $test.map_reduce(m, r, :out => {:merge => output_collection})
|
487
|
+
assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 1}
|
488
|
+
|
489
|
+
$test.remove
|
490
|
+
$test << {:user_id => 3}
|
491
|
+
res = $test.map_reduce(m, r, :out => {:reduce => output_collection})
|
492
|
+
assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 2}
|
493
|
+
|
494
|
+
assert_raises ArgumentError do
|
495
|
+
$test.map_reduce(m, r, :out => {:inline => 1})
|
496
|
+
end
|
497
|
+
|
498
|
+
$test.map_reduce(m, r, :raw => true, :out => {:inline => 1})
|
499
|
+
assert res["results"]
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
if VERSION > "1.3.0"
|
504
|
+
def test_find_and_modify
|
505
|
+
$test << { :a => 1, :processed => false }
|
506
|
+
$test << { :a => 2, :processed => false }
|
507
|
+
$test << { :a => 3, :processed => false }
|
508
|
+
|
509
|
+
$test.find_and_modify(:query => {}, :sort => [['a', -1]], :update => {"$set" => {:processed => true}})
|
510
|
+
|
511
|
+
assert $test.find_one({:a => 3})['processed']
|
512
|
+
end
|
513
|
+
|
514
|
+
def test_find_and_modify_with_invalid_options
|
515
|
+
$test << { :a => 1, :processed => false }
|
516
|
+
$test << { :a => 2, :processed => false }
|
517
|
+
$test << { :a => 3, :processed => false }
|
518
|
+
|
519
|
+
assert_raises Mongo::OperationFailure do
|
520
|
+
$test.find_and_modify(:blimey => {})
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
if VERSION >= "1.3.5"
|
526
|
+
def test_coll_stats
|
527
|
+
$test << {:n => 1}
|
528
|
+
$test.create_index("n")
|
529
|
+
stats = $test.stats
|
530
|
+
assert_equal "#{MONGO_TEST_$db}.test", stats['ns']
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
def test_saving_dates_pre_epoch
|
535
|
+
begin
|
536
|
+
$test.save({'date' => Time.utc(1600)})
|
537
|
+
assert_in_delta Time.utc(1600), $test.find_one()["date"], 2
|
538
|
+
rescue ArgumentError
|
539
|
+
# See note in test_date_before_epoch (BSONTest)
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
def test_save_symbol_find_string
|
544
|
+
$test.save(:foo => :mike, :foo1 => 'mike')
|
545
|
+
|
546
|
+
assert_equal :mike, $test.find_one(:foo => :mike)["foo"]
|
547
|
+
assert_equal :mike, $test.find_one("foo" => :mike)["foo"]
|
548
|
+
assert_equal 'mike', $test.find_one("foo" => :mike)["foo1"]
|
549
|
+
|
550
|
+
assert_equal :mike, $test.find_one(:foo => "mike")["foo"]
|
551
|
+
assert_equal :mike, $test.find_one("foo" => "mike")["foo"]
|
552
|
+
end
|
553
|
+
|
554
|
+
def test_limit_and_skip
|
555
|
+
10.times do |i|
|
556
|
+
$test.save(:foo => i)
|
557
|
+
end
|
558
|
+
|
559
|
+
assert_equal 5, $test.find({}, :skip => 5).next_document()["foo"]
|
560
|
+
assert_equal nil, $test.find({}, :skip => 10).next_document()
|
561
|
+
|
562
|
+
assert_equal 5, $test.find({}, :limit => 5).to_a.length
|
563
|
+
|
564
|
+
assert_equal 3, $test.find({}, :skip => 3, :limit => 5).next_document()["foo"]
|
565
|
+
assert_equal 5, $test.find({}, :skip => 3, :limit => 5).to_a.length
|
566
|
+
end
|
567
|
+
|
568
|
+
def test_large_limit
|
569
|
+
2000.times do |i|
|
570
|
+
$test.insert("x" => i, "y" => "mongomongo" * 1000)
|
571
|
+
end
|
572
|
+
|
573
|
+
assert_equal 2000, $test.count
|
574
|
+
|
575
|
+
i = 0
|
576
|
+
y = 0
|
577
|
+
$test.find({}, :limit => 1900).each do |doc|
|
578
|
+
i += 1
|
579
|
+
y += doc["x"]
|
580
|
+
end
|
581
|
+
|
582
|
+
assert_equal 1900, i
|
583
|
+
assert_equal 1804050, y
|
584
|
+
end
|
585
|
+
|
586
|
+
def test_small_limit
|
587
|
+
$test.insert("x" => "hello world")
|
588
|
+
$test.insert("x" => "goodbye world")
|
589
|
+
|
590
|
+
assert_equal 2, $test.count
|
591
|
+
|
592
|
+
x = 0
|
593
|
+
$test.find({}, :limit => 1).each do |doc|
|
594
|
+
x += 1
|
595
|
+
assert_equal "hello world", doc["x"]
|
596
|
+
end
|
597
|
+
|
598
|
+
assert_equal 1, x
|
599
|
+
end
|
600
|
+
|
601
|
+
def test_find_with_transformer
|
602
|
+
klass = Struct.new(:id, :a)
|
603
|
+
transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
|
604
|
+
cursor = $test.find({}, :transformer => transformer)
|
605
|
+
assert_equal(transformer, cursor.transformer)
|
606
|
+
end
|
607
|
+
|
608
|
+
def test_find_one_with_transformer
|
609
|
+
klass = Struct.new(:id, :a)
|
610
|
+
transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
|
611
|
+
id = $test.insert('a' => 1)
|
612
|
+
doc = $test.find_one(id, :transformer => transformer)
|
613
|
+
assert_instance_of(klass, doc)
|
614
|
+
end
|
615
|
+
|
616
|
+
def test_ensure_index
|
617
|
+
$test.drop_indexes
|
618
|
+
$test.insert("x" => "hello world")
|
619
|
+
assert_equal 1, $test.index_information.keys.count #default index
|
620
|
+
|
621
|
+
$test.ensure_index([["x", Mongo::DESCENDING]], {})
|
622
|
+
assert_equal 2, $test.index_information.keys.count
|
623
|
+
assert $test.index_information.keys.include? "x_-1"
|
624
|
+
|
625
|
+
$test.ensure_index([["x", Mongo::ASCENDING]])
|
626
|
+
assert $test.index_information.keys.include? "x_1"
|
627
|
+
|
628
|
+
$test.ensure_index([["type", 1], ["date", -1]])
|
629
|
+
assert $test.index_information.keys.include? "type_1_date_-1"
|
630
|
+
|
631
|
+
$test.drop_index("x_1")
|
632
|
+
assert_equal 3, $test.index_information.keys.count
|
633
|
+
$test.drop_index("x_-1")
|
634
|
+
assert_equal 2, $test.index_information.keys.count
|
635
|
+
|
636
|
+
$test.ensure_index([["x", Mongo::DESCENDING]], {})
|
637
|
+
assert_equal 3, $test.index_information.keys.count
|
638
|
+
assert $test.index_information.keys.include? "x_-1"
|
639
|
+
|
640
|
+
# Make sure that drop_index expires cache properly
|
641
|
+
$test.ensure_index([['a', 1]])
|
642
|
+
assert $test.index_information.keys.include?("a_1")
|
643
|
+
$test.drop_index("a_1")
|
644
|
+
assert !$test.index_information.keys.include?("a_1")
|
645
|
+
$test.ensure_index([['a', 1]])
|
646
|
+
assert $test.index_information.keys.include?("a_1")
|
647
|
+
$test.drop_index("a_1")
|
648
|
+
end
|
649
|
+
|
650
|
+
end
|
651
|
+
|
652
|
+
require 'minitest/spec'
|
653
|
+
|
654
|
+
describe "Grouping" do
|
655
|
+
before do
|
656
|
+
$test.remove
|
657
|
+
$test.save("a" => 1)
|
658
|
+
$test.save("b" => 1)
|
659
|
+
@initial = {"count" => 0}
|
660
|
+
@reduce_function = "function (obj, prev) { prev.count += inc_value; }"
|
661
|
+
@grp_opts = {:initial => @initial, :reduce => BSON::Code.new(@reduce_function, {"inc_value" => 1})}
|
662
|
+
end
|
663
|
+
|
664
|
+
it "should fail if missing required options" do
|
665
|
+
lambda { $test.group(:initial => {}) }.must_raise Mongo::MongoArgumentError
|
666
|
+
lambda { $test.group(:reduce => "foo") }.must_raise Mongo::MongoArgumentError
|
667
|
+
end
|
668
|
+
|
669
|
+
it "should group results using eval form" do
|
670
|
+
@grp_opts[:reduce] = BSON::Code.new(@reduce_function, {"inc_value" => 0.5})
|
671
|
+
$test.group( @grp_opts )[0]["count"].must_equal 1
|
672
|
+
|
673
|
+
@grp_opts[:reduce] = BSON::Code.new(@reduce_function, {"inc_value" => 1})
|
674
|
+
$test.group( @grp_opts )[0]["count"].must_equal 2
|
675
|
+
|
676
|
+
@grp_opts[:reduce] = BSON::Code.new(@reduce_function, {"inc_value" => 2})
|
677
|
+
$test.group( @grp_opts )[0]["count"].must_equal 4
|
678
|
+
end
|
679
|
+
|
680
|
+
it "should finalize grouped results" do
|
681
|
+
@grp_opts[:finalize] = "function(doc) {doc.f = doc.count + 200; }"
|
682
|
+
$test.group( @grp_opts )[0]["f"].must_equal 202
|
683
|
+
end
|
684
|
+
end
|
685
|
+
|
686
|
+
describe "Grouping with key" do
|
687
|
+
before do
|
688
|
+
$test.remove
|
689
|
+
$test.save("a" => 1, "pop" => 100)
|
690
|
+
$test.save("a" => 1, "pop" => 100)
|
691
|
+
$test.save("a" => 2, "pop" => 100)
|
692
|
+
$test.save("a" => 2, "pop" => 100)
|
693
|
+
@initial = {"count" => 0, "foo" => 1}
|
694
|
+
@reduce_function = "function (obj, prev) { prev.count += obj.pop; }"
|
695
|
+
end
|
696
|
+
|
697
|
+
it "should group" do
|
698
|
+
result = $test.group(:key => ['a'], :initial => @initial, :reduce => @reduce_function)
|
699
|
+
true.must_equal result.all? { |r| r['count'] == 200 }
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
describe "Grouping with a key function" do
|
704
|
+
before do
|
705
|
+
$test.remove
|
706
|
+
$test.save("a" => 1)
|
707
|
+
$test.save("a" => 2)
|
708
|
+
$test.save("a" => 3)
|
709
|
+
$test.save("a" => 4)
|
710
|
+
$test.save("a" => 5)
|
711
|
+
@initial = {"count" => 0}
|
712
|
+
@keyf = "function (doc) { if(doc.a % 2 == 0) { return {even: true}; } else {return {odd: true}} };"
|
713
|
+
@reduce = "function (obj, prev) { prev.count += 1; }"
|
714
|
+
end
|
715
|
+
|
716
|
+
it "should group results" do
|
717
|
+
results = $test.group(:keyf => @keyf, :initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
|
718
|
+
true.must_equal results[0]['even'] && results[0]['count'] == 2.0
|
719
|
+
true.must_equal results[1]['odd'] && results[1]['count'] == 3.0
|
720
|
+
end
|
721
|
+
|
722
|
+
it "should group filtered results" do
|
723
|
+
results = $test.group(:keyf => @keyf, :cond => {:a => {'$ne' => 2}},
|
724
|
+
:initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
|
725
|
+
true.must_equal results[0]['even'] && results[0]['count'] == 1.0
|
726
|
+
true.must_equal results[1]['odd'] && results[1]['count'] == 3.0
|
727
|
+
end
|
728
|
+
end
|
729
|
+
|
730
|
+
describe "A collection with two records" do
|
731
|
+
before do
|
732
|
+
@collection = $db.collection('test-collection')
|
733
|
+
@collection.remove
|
734
|
+
@collection.insert({:name => "Jones"})
|
735
|
+
@collection.insert({:name => "Smith"})
|
736
|
+
end
|
737
|
+
|
738
|
+
it "should have two records" do
|
739
|
+
@collection.size.must_equal 2
|
740
|
+
end
|
741
|
+
|
742
|
+
it "should remove the two records" do
|
743
|
+
@collection.remove()
|
744
|
+
@collection.size.must_equal 0
|
745
|
+
end
|
746
|
+
|
747
|
+
it "should remove all records if an empty document is specified" do
|
748
|
+
@collection.remove({})
|
749
|
+
@collection.find.count.must_equal 0
|
750
|
+
end
|
751
|
+
|
752
|
+
it "should remove only matching records" do
|
753
|
+
@collection.remove({:name => "Jones"})
|
754
|
+
@collection.size.must_equal 1
|
755
|
+
end
|
756
|
+
end
|
757
|
+
|
758
|
+
describe "Drop index " do
|
759
|
+
before do
|
760
|
+
$db.drop_collection('test-collection')
|
761
|
+
@collection = $db.collection('test-collection')
|
762
|
+
end
|
763
|
+
|
764
|
+
it "should drop an index" do
|
765
|
+
@collection.create_index([['a', Mongo::ASCENDING]])
|
766
|
+
assert @collection.index_information['a_1']
|
767
|
+
@collection.drop_index([['a', Mongo::ASCENDING]])
|
768
|
+
assert_nil @collection.index_information['a_1']
|
769
|
+
end
|
770
|
+
|
771
|
+
it "should drop an index which was given a specific name" do
|
772
|
+
@collection.create_index([['a', Mongo::DESCENDING]], {:name => 'i_will_not_fear'})
|
773
|
+
assert @collection.index_information['i_will_not_fear']
|
774
|
+
@collection.drop_index([['a', Mongo::DESCENDING]])
|
775
|
+
assert_nil @collection.index_information['i_will_not_fear']
|
776
|
+
end
|
777
|
+
|
778
|
+
it "should drops an composite index" do
|
779
|
+
@collection.create_index([['a', Mongo::DESCENDING], ['b', Mongo::ASCENDING]])
|
780
|
+
assert @collection.index_information['a_-1_b_1']
|
781
|
+
@collection.drop_index([['a', Mongo::DESCENDING], ['b', Mongo::ASCENDING]])
|
782
|
+
assert_nil @collection.index_information['a_-1_b_1']
|
783
|
+
end
|
784
|
+
|
785
|
+
it "should drops an index with symbols" do
|
786
|
+
@collection.create_index([['a', Mongo::DESCENDING], [:b, Mongo::ASCENDING]])
|
787
|
+
assert @collection.index_information['a_-1_b_1']
|
788
|
+
@collection.drop_index([['a', Mongo::DESCENDING], [:b, Mongo::ASCENDING]])
|
789
|
+
assert_nil @collection.index_information['a_-1_b_1']
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
793
|
+
describe "Creating indexes " do
|
794
|
+
before do
|
795
|
+
$db.drop_collection('geo')
|
796
|
+
$db.drop_collection('test-collection')
|
797
|
+
@collection = $db.collection('test-collection')
|
798
|
+
@geo = $db.collection('geo')
|
799
|
+
end
|
800
|
+
|
801
|
+
it "should create index using symbols" do
|
802
|
+
@collection.create_index :foo, :name => :bar
|
803
|
+
@geo.create_index :goo, :name => :baz
|
804
|
+
assert @collection.index_information['bar']
|
805
|
+
@collection.drop_index :bar
|
806
|
+
assert_nil @collection.index_information['bar']
|
807
|
+
assert @geo.index_information['baz']
|
808
|
+
@geo.drop_index(:baz)
|
809
|
+
assert_nil @geo.index_information['baz']
|
810
|
+
end
|
811
|
+
|
812
|
+
it "should create a geospatial index" do
|
813
|
+
@geo.save({'loc' => [-100, 100]})
|
814
|
+
@geo.create_index([['loc', Mongo::GEO2D]])
|
815
|
+
assert @geo.index_information['loc_2d']
|
816
|
+
end
|
817
|
+
|
818
|
+
it "should create a unique index" do
|
819
|
+
@collection.create_index([['a', Mongo::ASCENDING]], :unique => true)
|
820
|
+
assert @collection.index_information['a_1']['unique'] == true
|
821
|
+
end
|
822
|
+
|
823
|
+
it "should drop duplicates" do
|
824
|
+
@collection.insert({:a => 1})
|
825
|
+
@collection.insert({:a => 1})
|
826
|
+
assert_equal 2, @collection.find({:a => 1}).count
|
827
|
+
@collection.create_index([['a', Mongo::ASCENDING]], :unique => true, :dropDups => true)
|
828
|
+
assert_equal 1, @collection.find({:a => 1}).count
|
829
|
+
end
|
830
|
+
|
831
|
+
it "should drop duplicates with ruby-like drop_dups key" do
|
832
|
+
@collection.insert({:a => 1})
|
833
|
+
@collection.insert({:a => 1})
|
834
|
+
assert_equal 2, @collection.find({:a => 1}).count
|
835
|
+
@collection.create_index([['a', Mongo::ASCENDING]], :unique => true, :drop_dups => true)
|
836
|
+
assert_equal 1, @collection.find({:a => 1}).count
|
837
|
+
end
|
838
|
+
|
839
|
+
it "should drop duplicates with ensure_index and drop_dups key" do
|
840
|
+
@collection.insert({:a => 1})
|
841
|
+
@collection.insert({:a => 1})
|
842
|
+
assert_equal 2, @collection.find({:a => 1}).count
|
843
|
+
@collection.ensure_index([['a', Mongo::ASCENDING]], :unique => true, :drop_dups => true)
|
844
|
+
assert_equal 1, @collection.find({:a => 1}).count
|
845
|
+
end
|
846
|
+
|
847
|
+
it "should create an index in the background" do
|
848
|
+
if VERSION > '1.3.1'
|
849
|
+
@collection.create_index([['b', Mongo::ASCENDING]], :background => true)
|
850
|
+
assert @collection.index_information['b_1']['background'] == true
|
851
|
+
else
|
852
|
+
assert true
|
853
|
+
end
|
854
|
+
end
|
855
|
+
|
856
|
+
it "should require an array of arrays" do
|
857
|
+
assert_raises Mongo::MongoArgumentError do
|
858
|
+
@collection.create_index(['c', Mongo::ASCENDING])
|
859
|
+
end
|
860
|
+
end
|
861
|
+
|
862
|
+
it "should enforce proper index types" do
|
863
|
+
assert_raises Mongo::MongoArgumentError do
|
864
|
+
@collection.create_index([['c', 'blah']])
|
865
|
+
end
|
866
|
+
end
|
867
|
+
|
868
|
+
it "should raise an error if index name is greater than 128" do
|
869
|
+
assert_raises Mongo::OperationFailure do
|
870
|
+
@collection.create_index([['a' * 25, 1], ['b' * 25, 1],
|
871
|
+
['c' * 25, 1], ['d' * 25, 1], ['e' * 25, 1]])
|
872
|
+
end
|
873
|
+
end
|
874
|
+
|
875
|
+
it "should allow for an alternate name to be specified" do
|
876
|
+
@collection.create_index([['a' * 25, 1], ['b' * 25, 1],
|
877
|
+
['c' * 25, 1], ['d' * 25, 1], ['e' * 25, 1]], :name => 'foo_index')
|
878
|
+
assert @collection.index_information['foo_index']
|
879
|
+
end
|
880
|
+
|
881
|
+
it "should allow creation of multiple indexes" do
|
882
|
+
assert @collection.create_index([['a', 1]])
|
883
|
+
assert @collection.create_index([['a', 1]])
|
884
|
+
end
|
885
|
+
|
886
|
+
describe "with an index created" do
|
887
|
+
before do
|
888
|
+
@collection.create_index([['b', 1], ['a', 1]])
|
889
|
+
end
|
890
|
+
|
891
|
+
it "should return properly ordered index information" do
|
892
|
+
assert @collection.index_information['b_1_a_1']
|
893
|
+
end
|
894
|
+
end
|
895
|
+
end
|
896
|
+
|
897
|
+
# describe "Capped collections" do
|
898
|
+
# before do
|
899
|
+
# $db.drop_collection('log')
|
900
|
+
# @capped = $db.create_collection('log', :capped => true, :size => 1024)
|
901
|
+
|
902
|
+
# 10.times { |n| @capped.insert({:n => n}) }
|
903
|
+
# end
|
904
|
+
|
905
|
+
# it "should find using a standard cursor" do
|
906
|
+
# cursor = @capped.find
|
907
|
+
# 10.times do
|
908
|
+
# assert cursor.next_document
|
909
|
+
# end
|
910
|
+
# assert_nil cursor.next_document
|
911
|
+
# @capped.insert({:n => 100})
|
912
|
+
# assert_nil cursor.next_document
|
913
|
+
# end
|
914
|
+
|
915
|
+
# it "should fail tailable cursor on a non-capped collection" do
|
916
|
+
# col = $db['regular-collection']
|
917
|
+
# col.insert({:a => 1000})
|
918
|
+
# tail = Cursor.new(col, :tailable => true, :order => [['$natural', 1]])
|
919
|
+
# assert_raises OperationFailure do
|
920
|
+
# tail.next_document
|
921
|
+
# end
|
922
|
+
# end
|
923
|
+
|
924
|
+
# it "should find using a tailable cursor" do
|
925
|
+
# tail = Cursor.new(@capped, :tailable => true, :order => [['$natural', 1]])
|
926
|
+
# 10.times do
|
927
|
+
# assert tail.next_document
|
928
|
+
# end
|
929
|
+
# assert_nil tail.next_document
|
930
|
+
# @capped.insert({:n => 100})
|
931
|
+
# assert tail.next_document
|
932
|
+
# end
|
933
|
+
# end
|