jmongo 1.1.1 → 1.1.2
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/Rakefile +14 -1
- data/jmongo.gemspec +2 -2
- data/lib/jmongo/collection.rb +32 -50
- data/lib/jmongo/connection.rb +24 -9
- data/lib/jmongo/db.rb +42 -32
- data/lib/jmongo/mongo/bson.rb +26 -2
- data/lib/jmongo/mongo/collection.rb +24 -16
- data/lib/jmongo/mongo/connection.rb +3 -2
- data/lib/jmongo/mongo/db.rb +13 -13
- data/lib/jmongo/mongo/jmongo.rb +21 -1
- data/lib/jmongo/mongo/ruby_ext.rb +6 -0
- data/lib/jmongo/mongo/utils.rb +48 -0
- data/lib/jmongo/version.rb +1 -1
- data/test/collection_test.rb +273 -288
- data/test/cursor_test.rb +130 -144
- data/test/db_api_test.rb +267 -284
- data/test/test_helper.rb +43 -14
- metadata +26 -29
@@ -7,14 +7,14 @@ module Mongo
|
|
7
7
|
private
|
8
8
|
|
9
9
|
def name_from opts
|
10
|
-
return unless (opts[:name] || opts['name'])
|
11
10
|
name = opts.delete(:name) || opts.delete('name')
|
12
11
|
name ? name.to_s : nil
|
13
12
|
end
|
14
13
|
|
15
14
|
def _drop_index(spec)
|
16
15
|
name = generate_index_name(spec.is_a?(String) || spec.is_a?(Symbol) ? spec : parse_index_spec(spec))
|
17
|
-
|
16
|
+
info = @db.index_information(@name)
|
17
|
+
idx = info.values.select do |entry|
|
18
18
|
entry['name'] == name || name == generate_index_name(entry['key'])
|
19
19
|
end
|
20
20
|
if idx.nil? || idx.empty?
|
@@ -23,17 +23,24 @@ module Mongo
|
|
23
23
|
@j_collection.dropIndexes(idx.first['name'].to_s)
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
27
|
-
|
26
|
+
def _ensure_index(obj, opts = {})
|
27
|
+
opts[:ensure] = true
|
28
|
+
_create_index(obj, opts)
|
29
|
+
end
|
30
|
+
|
31
|
+
def _create_index(obj, opts = {})
|
32
|
+
opt_name = name_from(opts)
|
33
|
+
opts[:dropDups] = opts.delete(:drop_dups) if opts.has_key?(:drop_dups)
|
28
34
|
field_spec = parse_index_spec(obj)
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
name = generate_index_name(field_spec) unless name
|
34
|
-
opts['name'] = name
|
35
|
+
name = generate_index_name(field_spec)
|
36
|
+
opts['name'] = opt_name || name
|
37
|
+
opts['ns'] = @j_collection.full_name
|
35
38
|
begin
|
36
|
-
|
39
|
+
if opts.delete(:ensure)
|
40
|
+
@j_collection.ensure_index(to_dbobject(field_spec),to_dbobject(opts))
|
41
|
+
else
|
42
|
+
@j_collection.create_index(to_dbobject(field_spec),to_dbobject(opts))
|
43
|
+
end
|
37
44
|
rescue => e
|
38
45
|
if opts[:dropDups] && e.message =~ /E11000/
|
39
46
|
# NOP. If the user is intentionally dropping dups, we can ignore duplicate key errors.
|
@@ -42,7 +49,7 @@ module Mongo
|
|
42
49
|
raise Mongo::OperationFailure, msg
|
43
50
|
end
|
44
51
|
end
|
45
|
-
name
|
52
|
+
opts['name']
|
46
53
|
end
|
47
54
|
|
48
55
|
def generate_index_name(spec)
|
@@ -93,7 +100,7 @@ module Mongo
|
|
93
100
|
out << res if res
|
94
101
|
end
|
95
102
|
if to_do.size != out.size
|
96
|
-
msg = "Failed to insert document #{obj.inspect}, duplicate key"
|
103
|
+
msg = "Failed to insert document #{obj.inspect}, duplicate key, E11000"
|
97
104
|
raise(Mongo::OperationFailure, msg)
|
98
105
|
end
|
99
106
|
else
|
@@ -102,7 +109,7 @@ module Mongo
|
|
102
109
|
rescue => ex
|
103
110
|
if ex.message =~ /E11000/
|
104
111
|
msg = "Failed to insert document #{obj.inspect}, duplicate key, E11000"
|
105
|
-
raise(Mongo::OperationFailure, msg)
|
112
|
+
raise(Mongo::OperationFailure, msg) if concern.w > 0
|
106
113
|
else
|
107
114
|
msg = "Failed to insert document #{obj.inspect} db error: #{ex.message}"
|
108
115
|
raise Mongo::MongoDBError, msg
|
@@ -145,11 +152,12 @@ module Mongo
|
|
145
152
|
|
146
153
|
def update_documents(selector, document, upsert=false, multi=false, safe=nil)
|
147
154
|
begin
|
148
|
-
|
155
|
+
concern = @db.write_concern(safe)
|
156
|
+
@j_collection.update(to_dbobject(selector),to_dbobject(document), upsert, multi, concern)
|
149
157
|
rescue => ex
|
150
158
|
if ex.message =~ /E11001/
|
151
159
|
msg = "Failed to update document #{document.inspect}, duplicate key"
|
152
|
-
raise(Mongo::OperationFailure, msg)
|
160
|
+
raise(Mongo::OperationFailure, msg) if concern.w > 0
|
153
161
|
else
|
154
162
|
msg = "Failed to update document #{document.inspect} db error: #{ex.message}"
|
155
163
|
raise Mongo::MongoDBError, msg
|
@@ -18,8 +18,9 @@ module Mongo
|
|
18
18
|
|
19
19
|
module ClassMethods
|
20
20
|
URI_RE = /^mongodb:\/\/(([-.\w]+):([^@]+)@)?([-.\w]+)(:([\w]+))?(\/([-\w]+))?/
|
21
|
-
OPTS_KEYS = %W[maxpoolsize
|
22
|
-
|
21
|
+
OPTS_KEYS = %W[maxpoolsize connecttimeoutms autoconnectretry
|
22
|
+
waitqueuemultiple waitqueuetimeoutms sockettimeoutms
|
23
|
+
slaveok safe w wtimeout fsync]
|
23
24
|
|
24
25
|
def _from_uri uri, opts={}
|
25
26
|
optarr = []
|
data/lib/jmongo/mongo/db.rb
CHANGED
@@ -13,15 +13,8 @@ module Mongo
|
|
13
13
|
#@collection.save({:doc => 'foo'}, :safe => {:w => 2, :wtimeout => 200, :fsync => true}) ---> new WriteConcern( 2 , 0 , true)
|
14
14
|
#@collection.save({:doc => 'foo'}, :safe => {:fsync => true}) ---> FSYNC_SAFE = new WriteConcern( 1 , 0 , true)
|
15
15
|
|
16
|
-
def write_concern(
|
17
|
-
|
18
|
-
return JMongo::WriteConcern.new(0) if safe.is_a?(FalseClass)
|
19
|
-
return JMongo::WriteConcern.new(1) if safe.is_a?(TrueClass)
|
20
|
-
return JMongo::WriteConcern.new(0) unless safe.is_a?(Hash)
|
21
|
-
w = safe[:w] || 1
|
22
|
-
t = safe[:wtimeout] || 0
|
23
|
-
f = !!(safe[:fsync] || false)
|
24
|
-
JMongo::WriteConcern.new(w, t, f) #dont laugh!
|
16
|
+
def write_concern(safe_)
|
17
|
+
self.class.write_concern(safe_ || self.safe || @connection.write_concern)
|
25
18
|
end
|
26
19
|
|
27
20
|
private
|
@@ -29,20 +22,27 @@ module Mongo
|
|
29
22
|
def exec_command(cmd)
|
30
23
|
cmd_hash = cmd.kind_of?(Hash) ? cmd : {cmd => 1}
|
31
24
|
cmd_res = @j_db.command(to_dbobject(cmd_hash))
|
32
|
-
from_dbobject
|
25
|
+
from_dbobject cmd_res
|
33
26
|
end
|
34
27
|
|
35
28
|
def do_eval(string, *args)
|
36
|
-
|
29
|
+
command(BSON::OrderedHash['$eval', string,'args', args])
|
37
30
|
end
|
38
31
|
|
39
|
-
def
|
40
|
-
@j_db.collection_exists(name)
|
32
|
+
def collection_exists?(name)
|
33
|
+
system_name?(name) || @j_db.collection_exists(name)
|
41
34
|
end
|
42
35
|
|
43
36
|
def get_last_error
|
44
37
|
from_dbobject @j_db.get_last_error
|
45
38
|
end
|
39
|
+
|
40
|
+
def _collections_info(coll_name=nil)
|
41
|
+
selector = {}
|
42
|
+
selector[:name] = full_collection_name(coll_name) if coll_name
|
43
|
+
coll = @j_db.get_collection(SYSTEM_NAMESPACE_COLLECTION)
|
44
|
+
from_dbobject(coll.find(to_dbobject(selector)))
|
45
|
+
end
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
data/lib/jmongo/mongo/jmongo.rb
CHANGED
@@ -3,7 +3,6 @@ module JMongo
|
|
3
3
|
java_import com.mongodb.BasicDBObject
|
4
4
|
java_import com.mongodb.Bytes
|
5
5
|
java_import com.mongodb.DB
|
6
|
-
java_import com.mongodb.DBRef
|
7
6
|
java_import com.mongodb.DBCollection
|
8
7
|
java_import com.mongodb.DBCursor
|
9
8
|
java_import com.mongodb.DBObject
|
@@ -16,6 +15,27 @@ module JMongo
|
|
16
15
|
java_import com.mongodb.MongoURI
|
17
16
|
java_import com.mongodb.MapReduceCommand
|
18
17
|
java_import com.mongodb.MapReduceOutput
|
18
|
+
|
19
|
+
SECS_TO_MILLI_FUNC = lambda { |v| v.to_f * 1_000 }
|
20
|
+
DO_NOTHING_FUNC = lambda { |v| v }
|
21
|
+
|
22
|
+
RUBY_JAVA_OPTIONS_KEYS = {
|
23
|
+
:pool_size => [:connections_per_host, DO_NOTHING_FUNC],
|
24
|
+
:pool_timeout => [:max_wait_time, SECS_TO_MILLI_FUNC],
|
25
|
+
:timeout => [:max_wait_time, SECS_TO_MILLI_FUNC],
|
26
|
+
:op_timeout => [:socket_timeout, SECS_TO_MILLI_FUNC],
|
27
|
+
:connect_timeout => [:connect_timeout, SECS_TO_MILLI_FUNC]
|
28
|
+
}
|
29
|
+
|
30
|
+
RUBY_JAVA_OPTIONS_KEYS.default = [nil, DO_NOTHING_FUNC]
|
31
|
+
|
32
|
+
def self.options_ruby2java_lu(key)
|
33
|
+
RUBY_JAVA_OPTIONS_KEYS[key].first || key
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.options_ruby2java_xf(key,val)
|
37
|
+
RUBY_JAVA_OPTIONS_KEYS[key].last[val] || val
|
38
|
+
end
|
19
39
|
end
|
20
40
|
|
21
41
|
class Java::ComMongodb::BasicDBObject
|
data/lib/jmongo/mongo/utils.rb
CHANGED
@@ -21,6 +21,52 @@ module Mongo
|
|
21
21
|
raise ex_class, msg ? "#{msg} - #{ex.message}" : ex.message
|
22
22
|
end
|
23
23
|
end
|
24
|
+
|
25
|
+
def system_name?(name)
|
26
|
+
name =~ /((^\$cmd)|(oplog\.\$main))/
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate_name(new_name)
|
30
|
+
unless [String, Symbol].include?(new_name.class)
|
31
|
+
raise TypeError, "db_name must be a string or symbol"
|
32
|
+
end
|
33
|
+
|
34
|
+
name = new_name.to_s
|
35
|
+
|
36
|
+
if name.empty?
|
37
|
+
raise Mongo::InvalidNSName, "collection names cannot be empty"
|
38
|
+
end
|
39
|
+
if name.include?("..")
|
40
|
+
raise Mongo::InvalidNSName, "collection names cannot contain '..'"
|
41
|
+
end
|
42
|
+
if name.include? "$"
|
43
|
+
raise Mongo::InvalidNSName, "collection names cannot contain '$'" unless name =~ /((^\$cmd)|(oplog\.\$main))/
|
44
|
+
end
|
45
|
+
if name.match(/^\./) || name.match(/\.$/)
|
46
|
+
raise Mongo::InvalidNSName, "collection names cannot start or end with '.'"
|
47
|
+
end
|
48
|
+
name
|
49
|
+
end
|
50
|
+
|
51
|
+
def prep_id(doc)
|
52
|
+
if doc[:_id] && !doc['_id']
|
53
|
+
doc['_id'] = doc.delete(:_id)
|
54
|
+
end
|
55
|
+
doc
|
56
|
+
end
|
57
|
+
|
58
|
+
def prep_hint(hint)
|
59
|
+
case hint
|
60
|
+
when String, Symbol
|
61
|
+
{hint => 1}
|
62
|
+
when Hash
|
63
|
+
hint
|
64
|
+
when nil
|
65
|
+
nil
|
66
|
+
else
|
67
|
+
Hash[hint.to_a.zip( [1]*hint.size )]
|
68
|
+
end
|
69
|
+
end
|
24
70
|
|
25
71
|
def prep_fields(fields)
|
26
72
|
case fields
|
@@ -75,6 +121,8 @@ module Mongo
|
|
75
121
|
Time.at(obj.get_time/1000.0)
|
76
122
|
when Java::OrgBsonTypes::Symbol
|
77
123
|
obj.toString.to_sym
|
124
|
+
when Java::JavaUtilRegex::Pattern
|
125
|
+
Regexp.new(obj.pattern, (obj.flags/2))
|
78
126
|
else
|
79
127
|
obj
|
80
128
|
end
|
data/lib/jmongo/version.rb
CHANGED
data/test/collection_test.rb
CHANGED
@@ -1,43 +1,27 @@
|
|
1
1
|
require './test/test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
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")
|
3
|
+
Cfg.connection :op_timeout => 10
|
4
|
+
Cfg.db
|
18
5
|
|
19
6
|
class TestCollection < MiniTest::Unit::TestCase
|
20
7
|
|
21
8
|
def setup
|
22
|
-
|
9
|
+
Cfg.clear_all
|
23
10
|
end
|
24
11
|
|
25
12
|
def test_capped_method
|
26
|
-
$db.drop_collection('normal')
|
27
13
|
|
28
|
-
|
29
|
-
assert
|
30
|
-
$db.drop_collection('normal')
|
14
|
+
Cfg.db.create_collection('normal').insert('x'=>3)
|
15
|
+
assert !Cfg.db['normal'].capped?
|
31
16
|
|
32
|
-
|
33
|
-
assert
|
34
|
-
$db.drop_collection('c')
|
17
|
+
Cfg.db.create_collection('c', :capped => true, :size => 100_000).insert('g'=>4)
|
18
|
+
assert Cfg.db['c'].capped?
|
35
19
|
end
|
36
20
|
|
37
21
|
def test_optional_pk_factory
|
38
|
-
@coll_default_pk =
|
22
|
+
@coll_default_pk = Cfg.db.collection('stuff')
|
39
23
|
assert_equal BSON::ObjectId, @coll_default_pk.pk_factory
|
40
|
-
@coll_default_pk =
|
24
|
+
@coll_default_pk = Cfg.db.create_collection('more-stuff')
|
41
25
|
assert_equal BSON::ObjectId, @coll_default_pk.pk_factory
|
42
26
|
|
43
27
|
# Create a db with a pk_factory.
|
@@ -56,74 +40,71 @@ class TestCollection < MiniTest::Unit::TestCase
|
|
56
40
|
end
|
57
41
|
|
58
42
|
def test_pk_factory_on_collection
|
59
|
-
@coll2 = Collection.new('foo',
|
43
|
+
@coll2 = Collection.new('foo', Cfg.db, :pk => TestPK)
|
60
44
|
assert_equal TestPK, @coll2.pk_factory
|
61
45
|
end
|
62
46
|
|
63
47
|
def test_valid_names
|
64
48
|
assert_raises Mongo::InvalidNSName do
|
65
|
-
|
49
|
+
Cfg.db["te$t"]
|
66
50
|
end
|
67
51
|
|
68
52
|
assert_raises Mongo::InvalidNSName do
|
69
|
-
|
53
|
+
Cfg.db['$main']
|
70
54
|
end
|
71
55
|
|
72
|
-
assert
|
73
|
-
assert
|
56
|
+
assert Cfg.db['$cmd']
|
57
|
+
assert Cfg.db['oplog.$main']
|
74
58
|
end
|
75
59
|
|
76
60
|
def test_collection
|
77
|
-
assert_kind_of Collection,
|
78
|
-
assert_equal
|
79
|
-
assert_equal
|
61
|
+
assert_kind_of Collection, Cfg.db["test"]
|
62
|
+
assert_equal Cfg.db["test"].name(), Cfg.db.collection("test").name()
|
63
|
+
assert_equal Cfg.db["test"].name(), Cfg.db[:test].name()
|
80
64
|
|
81
|
-
assert_kind_of Collection,
|
82
|
-
assert_equal
|
83
|
-
assert_equal
|
65
|
+
assert_kind_of Collection, Cfg.db["test"]["foo"]
|
66
|
+
assert_equal Cfg.db["test"]["foo"].name(), Cfg.db.collection("test.foo").name()
|
67
|
+
assert_equal Cfg.db["test"]["foo"].name(), Cfg.db["test.foo"].name()
|
84
68
|
|
85
|
-
|
86
|
-
|
87
|
-
assert_equal 5,
|
69
|
+
Cfg.db["test"]["foo"].remove
|
70
|
+
Cfg.db["test"]["foo"].insert("x" => 5)
|
71
|
+
assert_equal 5, Cfg.db.collection("test.foo").find_one()["x"]
|
88
72
|
end
|
89
73
|
|
90
74
|
def test_rename_collection
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
@col = $db.create_collection('foo1')
|
75
|
+
@col = Cfg.db.create_collection('foo1')
|
76
|
+
@col.insert("x" => 5) #must insert something to actually create collection
|
95
77
|
assert_equal 'foo1', @col.name
|
96
|
-
|
97
78
|
@col.rename('bar1')
|
98
79
|
assert_equal 'bar1', @col.name
|
99
80
|
end
|
100
81
|
|
101
82
|
def test_nil_id
|
102
83
|
skip("The Java driver does not allow nil _id")
|
103
|
-
assert_equal 5,
|
104
|
-
assert_equal 5,
|
105
|
-
assert_equal nil,
|
106
|
-
assert_equal "baz",
|
84
|
+
assert_equal 5, Cfg.test.insert({"_id" => 5, "foo" => "bar"}, {:safe => true})
|
85
|
+
assert_equal 5, Cfg.test.save({"_id" => 5, "foo" => "baz"}, {:safe => true})
|
86
|
+
assert_equal nil, Cfg.test.find_one("foo" => "bar")
|
87
|
+
assert_equal "baz", Cfg.test.find_one(:_id => 5)["foo"]
|
107
88
|
assert_raises OperationFailure do
|
108
|
-
|
89
|
+
Cfg.test.insert({"_id" => 5, "foo" => "bar"}, {:safe => true})
|
109
90
|
end
|
110
91
|
|
111
|
-
assert_equal nil,
|
112
|
-
assert_equal nil,
|
113
|
-
assert_equal nil,
|
114
|
-
assert_equal "baz",
|
92
|
+
assert_equal nil, Cfg.test.insert({"_id" => nil, "foo" => "bar"}, {:safe => true})
|
93
|
+
assert_equal nil, Cfg.test.save({"_id" => nil, "foo" => "baz"}, {:safe => true})
|
94
|
+
assert_equal nil, Cfg.test.find_one("foo" => "bar")
|
95
|
+
assert_equal "baz", Cfg.test.find_one(:_id => nil)["foo"]
|
115
96
|
assert_raises OperationFailure do
|
116
|
-
|
97
|
+
Cfg.test.insert({"_id" => nil, "foo" => "bar"}, {:safe => true})
|
117
98
|
end
|
118
99
|
assert_raises OperationFailure do
|
119
|
-
|
100
|
+
Cfg.test.insert({:_id => nil, "foo" => "bar"}, {:safe => true})
|
120
101
|
end
|
121
102
|
end
|
122
103
|
|
123
|
-
if
|
104
|
+
if Cfg.version > "1.1"
|
124
105
|
def setup_for_distinct
|
125
|
-
|
126
|
-
|
106
|
+
Cfg.test.remove
|
107
|
+
Cfg.test.insert([{:a => 0, :b => {:c => "a"}},
|
127
108
|
{:a => 1, :b => {:c => "b"}},
|
128
109
|
{:a => 1, :b => {:c => "c"}},
|
129
110
|
{:a => 2, :b => {:c => "a"}},
|
@@ -133,48 +114,48 @@ class TestCollection < MiniTest::Unit::TestCase
|
|
133
114
|
|
134
115
|
def test_distinct_queries
|
135
116
|
setup_for_distinct
|
136
|
-
assert_equal [0, 1, 2, 3],
|
137
|
-
assert_equal ["a", "b", "c"],
|
117
|
+
assert_equal [0, 1, 2, 3], Cfg.test.distinct(:a).sort
|
118
|
+
assert_equal ["a", "b", "c"], Cfg.test.distinct("b.c").sort
|
138
119
|
end
|
139
120
|
|
140
|
-
if
|
121
|
+
if Cfg.version >= "1.2"
|
141
122
|
def test_filter_collection_with_query
|
142
123
|
setup_for_distinct
|
143
|
-
assert_equal [2, 3],
|
124
|
+
assert_equal [2, 3], Cfg.test.distinct(:a, {:a => {"$gt" => 1}}).sort
|
144
125
|
end
|
145
126
|
|
146
127
|
def test_filter_nested_objects
|
147
128
|
setup_for_distinct
|
148
|
-
assert_equal ["a", "b"],
|
129
|
+
assert_equal ["a", "b"], Cfg.test.distinct("b.c", {"b.c" => {"$ne" => "c"}}).sort
|
149
130
|
end
|
150
131
|
end
|
151
132
|
end
|
152
133
|
|
153
134
|
def test_safe_insert
|
154
|
-
|
135
|
+
Cfg.test.create_index("hello", :unique => true)
|
155
136
|
a = {"hello" => "world"}
|
156
|
-
|
157
|
-
|
158
|
-
assert(
|
137
|
+
Cfg.test.insert(a)
|
138
|
+
Cfg.test.insert(a)
|
139
|
+
assert(Cfg.db.get_last_error['err'].include?("11000"))
|
159
140
|
|
160
141
|
assert_raises OperationFailure do
|
161
|
-
|
142
|
+
Cfg.test.insert(a, :safe => true)
|
162
143
|
end
|
163
144
|
end
|
164
145
|
|
165
146
|
def test_bulk_insert_with_continue_on_error
|
166
|
-
if
|
167
|
-
|
147
|
+
if Cfg.version >= "2.0"
|
148
|
+
Cfg.test.create_index([["foo", 1]], :unique => true)
|
168
149
|
docs = []
|
169
150
|
docs << {:foo => 1}
|
170
151
|
docs << {:foo => 1}
|
171
152
|
docs << {:foo => 2}
|
172
153
|
docs << {:foo => 3}
|
173
154
|
assert_raises OperationFailure do
|
174
|
-
|
155
|
+
Cfg.test.insert(docs, :safe => true)
|
175
156
|
end
|
176
|
-
assert_equal 1,
|
177
|
-
|
157
|
+
assert_equal 1, Cfg.test.count
|
158
|
+
Cfg.test.remove
|
178
159
|
|
179
160
|
docs = []
|
180
161
|
docs << {:foo => 1}
|
@@ -183,12 +164,12 @@ class TestCollection < MiniTest::Unit::TestCase
|
|
183
164
|
docs << {:foo => 3}
|
184
165
|
docs << {:foo => 3}
|
185
166
|
assert_raises OperationFailure do
|
186
|
-
|
167
|
+
Cfg.test.insert(docs, :safe => true, :continue_on_error => true)
|
187
168
|
end
|
188
|
-
assert_equal 3,
|
169
|
+
assert_equal 3, Cfg.test.count
|
189
170
|
|
190
|
-
|
191
|
-
|
171
|
+
Cfg.test.remove
|
172
|
+
Cfg.test.drop_index("foo_1")
|
192
173
|
end
|
193
174
|
end
|
194
175
|
|
@@ -200,70 +181,70 @@ class TestCollection < MiniTest::Unit::TestCase
|
|
200
181
|
end
|
201
182
|
|
202
183
|
assert_raises InvalidOperation do
|
203
|
-
|
184
|
+
Cfg.test.insert(docs)
|
204
185
|
end
|
205
186
|
end
|
206
187
|
|
207
188
|
def test_update
|
208
|
-
id1 =
|
209
|
-
|
210
|
-
assert_equal 1,
|
211
|
-
assert_equal 6,
|
189
|
+
id1 = Cfg.test.save("x" => 5)
|
190
|
+
Cfg.test.update({}, {"$inc" => {"x" => 1}})
|
191
|
+
assert_equal 1, Cfg.test.count()
|
192
|
+
assert_equal 6, Cfg.test.find_one(:_id => id1)["x"]
|
212
193
|
|
213
|
-
id2 =
|
214
|
-
|
215
|
-
assert_equal 7,
|
216
|
-
assert_equal 1,
|
194
|
+
id2 = Cfg.test.save("x" => 1)
|
195
|
+
Cfg.test.update({"x" => 6}, {"$inc" => {"x" => 1}})
|
196
|
+
assert_equal 7, Cfg.test.find_one(:_id => id1)["x"]
|
197
|
+
assert_equal 1, Cfg.test.find_one(:_id => id2)["x"]
|
217
198
|
end
|
218
199
|
|
219
200
|
def test_multi_update
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
assert_equal 3,
|
201
|
+
Cfg.test.save("num" => 10)
|
202
|
+
Cfg.test.save("num" => 10)
|
203
|
+
Cfg.test.save("num" => 10)
|
204
|
+
assert_equal 3, Cfg.test.count
|
224
205
|
|
225
|
-
|
226
|
-
|
206
|
+
Cfg.test.update({"num" => 10}, {"$set" => {"num" => 100}}, :multi => true)
|
207
|
+
Cfg.test.find.each do |doc|
|
227
208
|
assert_equal 100, doc["num"]
|
228
209
|
end
|
229
210
|
end
|
230
211
|
|
231
212
|
def test_upsert
|
232
|
-
|
233
|
-
|
213
|
+
Cfg.test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
|
214
|
+
Cfg.test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
|
234
215
|
|
235
|
-
assert_equal 1,
|
236
|
-
assert_equal 2,
|
216
|
+
assert_equal 1, Cfg.test.count()
|
217
|
+
assert_equal 2, Cfg.test.find_one()["count"]
|
237
218
|
end
|
238
219
|
|
239
220
|
def test_safe_update
|
240
|
-
|
241
|
-
|
242
|
-
|
221
|
+
Cfg.test.create_index("x", :unique => true)
|
222
|
+
Cfg.test.insert("x" => 5)
|
223
|
+
Cfg.test.insert("x" => 10)
|
243
224
|
|
244
225
|
# Can update an indexed collection.
|
245
|
-
|
246
|
-
assert
|
226
|
+
Cfg.test.update({}, {"$inc" => {"x" => 1}})
|
227
|
+
assert !Cfg.db.error?
|
247
228
|
|
248
229
|
# Can't duplicate an index.
|
249
230
|
assert_raises OperationFailure do
|
250
|
-
|
231
|
+
Cfg.test.update({}, {"x" => 10}, :safe => true)
|
251
232
|
end
|
252
233
|
end
|
253
234
|
|
254
235
|
def test_safe_save
|
255
|
-
|
236
|
+
Cfg.test.create_index("hello", :unique => true)
|
256
237
|
|
257
|
-
|
258
|
-
|
238
|
+
Cfg.test.save("hello" => "world")
|
239
|
+
Cfg.test.save("hello" => "world")
|
259
240
|
|
260
241
|
assert_raises OperationFailure do
|
261
|
-
|
242
|
+
Cfg.test.save({"hello" => "world"}, :safe => true)
|
262
243
|
end
|
263
244
|
end
|
264
245
|
|
265
246
|
def test_safe_remove
|
266
|
-
@conn =
|
247
|
+
@conn = Cfg.new_connection
|
267
248
|
@db = @conn[MONGO_TEST_DB]
|
268
249
|
@test = @db['test-safe-remove']
|
269
250
|
@test.save({:a => 50})
|
@@ -272,135 +253,135 @@ class TestCollection < MiniTest::Unit::TestCase
|
|
272
253
|
end
|
273
254
|
|
274
255
|
def test_remove_return_value
|
275
|
-
assert_equal true,
|
256
|
+
assert_equal true, Cfg.test.remove({})
|
276
257
|
end
|
277
258
|
|
278
259
|
def test_count
|
279
260
|
|
280
|
-
assert_equal 0,
|
281
|
-
|
282
|
-
|
283
|
-
assert_equal 2,
|
261
|
+
assert_equal 0, Cfg.test.count
|
262
|
+
Cfg.test.save(:x => 1)
|
263
|
+
Cfg.test.save(:x => 2)
|
264
|
+
assert_equal 2, Cfg.test.count
|
284
265
|
|
285
|
-
assert_equal 1,
|
286
|
-
assert_equal 1,
|
287
|
-
assert_equal 0,
|
266
|
+
assert_equal 1, Cfg.test.count(:query => {:x => 1})
|
267
|
+
assert_equal 1, Cfg.test.count(:limit => 1)
|
268
|
+
assert_equal 0, Cfg.test.count(:skip => 2)
|
288
269
|
end
|
289
270
|
|
290
271
|
# Note: #size is just an alias for #count.
|
291
272
|
def test_size
|
292
|
-
assert_equal 0,
|
293
|
-
assert_equal
|
294
|
-
|
295
|
-
|
296
|
-
assert_equal
|
273
|
+
assert_equal 0, Cfg.test.count
|
274
|
+
assert_equal Cfg.test.size, Cfg.test.count
|
275
|
+
Cfg.test.save("x" => 1)
|
276
|
+
Cfg.test.save("x" => 2)
|
277
|
+
assert_equal Cfg.test.size, Cfg.test.count
|
297
278
|
end
|
298
279
|
|
299
280
|
def test_no_timeout_option
|
300
281
|
|
301
282
|
assert_raises ArgumentError, "Timeout can be set to false only when #find is invoked with a block." do
|
302
|
-
|
283
|
+
Cfg.test.find({}, :timeout => false)
|
303
284
|
end
|
304
285
|
|
305
|
-
|
286
|
+
Cfg.test.find({}, :timeout => false) do |cursor|
|
306
287
|
assert_equal 0, cursor.count
|
307
288
|
end
|
308
289
|
|
309
|
-
|
310
|
-
|
311
|
-
|
290
|
+
Cfg.test.save("x" => 1)
|
291
|
+
Cfg.test.save("x" => 2)
|
292
|
+
Cfg.test.find({}, :timeout => false) do |cursor|
|
312
293
|
assert_equal 2, cursor.count
|
313
294
|
end
|
314
295
|
end
|
315
296
|
|
316
297
|
def test_default_timeout
|
317
|
-
cursor =
|
298
|
+
cursor = Cfg.test.find
|
318
299
|
assert_equal true, cursor.timeout
|
319
300
|
end
|
320
301
|
|
321
302
|
def test_fields_as_hash
|
322
|
-
|
303
|
+
Cfg.test.save(:a => 1, :b => 1, :c => 1)
|
323
304
|
|
324
|
-
doc =
|
305
|
+
doc = Cfg.test.find_one({:a => 1}, :fields => {:b => 0})
|
325
306
|
assert_nil doc['b']
|
326
307
|
assert doc['a']
|
327
308
|
assert doc['c']
|
328
309
|
|
329
|
-
doc =
|
310
|
+
doc = Cfg.test.find_one({:a => 1}, :fields => {:a => 1, :b => 1})
|
330
311
|
assert_nil doc['c']
|
331
312
|
assert doc['a']
|
332
313
|
assert doc['b']
|
333
314
|
|
334
315
|
|
335
316
|
assert_raises Mongo::OperationFailure do
|
336
|
-
|
317
|
+
Cfg.test.find_one({:a => 1}, :fields => {:a => 1, :b => 0})
|
337
318
|
end
|
338
319
|
end
|
339
320
|
|
340
|
-
if
|
321
|
+
if Cfg.version >= "1.5.1"
|
341
322
|
def test_fields_with_slice
|
342
|
-
|
323
|
+
Cfg.test.save({:foo => [1, 2, 3, 4, 5, 6], :test => 'slice'})
|
343
324
|
|
344
|
-
doc =
|
325
|
+
doc = Cfg.test.find_one({:test => 'slice'}, :fields => {'foo' => {'$slice' => [0, 3]}})
|
345
326
|
assert_equal [1, 2, 3], doc['foo']
|
346
|
-
|
327
|
+
Cfg.test.remove
|
347
328
|
end
|
348
329
|
end
|
349
330
|
|
350
331
|
def test_find_one
|
351
|
-
id =
|
332
|
+
id = Cfg.test.save("hello" => "world", "foo" => "bar")
|
352
333
|
|
353
|
-
assert_equal "world",
|
354
|
-
assert_equal
|
355
|
-
assert_equal
|
356
|
-
assert_equal
|
357
|
-
assert_equal
|
358
|
-
assert_equal
|
334
|
+
assert_equal "world", Cfg.test.find_one()["hello"]
|
335
|
+
assert_equal Cfg.test.find_one(id), Cfg.test.find_one()
|
336
|
+
assert_equal Cfg.test.find_one(nil), Cfg.test.find_one()
|
337
|
+
assert_equal Cfg.test.find_one({}), Cfg.test.find_one()
|
338
|
+
assert_equal Cfg.test.find_one("hello" => "world"), Cfg.test.find_one()
|
339
|
+
assert_equal Cfg.test.find_one(BSON::OrderedHash["hello", "world"]), Cfg.test.find_one()
|
359
340
|
|
360
|
-
assert
|
361
|
-
assert
|
362
|
-
assert_equal ["_id"],
|
341
|
+
assert Cfg.test.find_one(nil, :fields => ["hello"]).include?("hello")
|
342
|
+
assert !Cfg.test.find_one(nil, :fields => ["foo"]).include?("hello")
|
343
|
+
assert_equal ["_id"], Cfg.test.find_one(nil, :fields => []).keys()
|
363
344
|
|
364
|
-
assert_equal nil,
|
365
|
-
assert_equal nil,
|
366
|
-
assert_equal nil,
|
345
|
+
assert_equal nil, Cfg.test.find_one("hello" => "foo")
|
346
|
+
assert_equal nil, Cfg.test.find_one(BSON::OrderedHash["hello", "foo"])
|
347
|
+
assert_equal nil, Cfg.test.find_one(ObjectId.new)
|
367
348
|
|
368
349
|
assert_raises TypeError do
|
369
|
-
|
350
|
+
Cfg.test.find_one(6)
|
370
351
|
end
|
371
352
|
end
|
372
353
|
|
373
354
|
def test_insert_adds_id
|
374
355
|
doc = {"hello" => "world"}
|
375
|
-
|
376
|
-
assert(doc.include?(:_id))
|
356
|
+
Cfg.test.insert(doc)
|
357
|
+
assert(doc.include?(:_id) || doc.include?('_id'))
|
377
358
|
|
378
359
|
docs = [{"hello" => "world"}, {"hello" => "world"}]
|
379
|
-
|
360
|
+
Cfg.test.insert(docs)
|
380
361
|
docs.each do |d|
|
381
|
-
assert(d.include?(:_id))
|
362
|
+
assert(d.include?(:_id) || doc.include?('_id'))
|
382
363
|
end
|
383
364
|
end
|
384
365
|
|
385
366
|
def test_save_adds_id
|
386
367
|
doc = {"hello" => "world"}
|
387
|
-
|
388
|
-
assert(doc.include?(:_id))
|
368
|
+
Cfg.test.save(doc)
|
369
|
+
assert(doc.include?(:_id) || doc.include?('_id'))
|
389
370
|
end
|
390
371
|
|
391
372
|
def test_optional_find_block
|
392
373
|
10.times do |i|
|
393
|
-
|
374
|
+
Cfg.test.save("i" => i)
|
394
375
|
end
|
395
376
|
|
396
377
|
x = nil
|
397
|
-
|
378
|
+
Cfg.test.find("i" => 2) { |cursor|
|
398
379
|
x = cursor.count()
|
399
380
|
}
|
400
381
|
assert_equal 1, x
|
401
382
|
|
402
383
|
i = 0
|
403
|
-
|
384
|
+
Cfg.test.find({}, :skip => 5) do |cursor|
|
404
385
|
cursor.each do |doc|
|
405
386
|
i = i + 1
|
406
387
|
end
|
@@ -408,173 +389,173 @@ class TestCollection < MiniTest::Unit::TestCase
|
|
408
389
|
assert_equal 5, i
|
409
390
|
|
410
391
|
c = nil
|
411
|
-
|
392
|
+
Cfg.test.find() do |cursor|
|
412
393
|
c = cursor
|
413
394
|
end
|
414
395
|
assert c.closed?
|
415
396
|
end
|
416
397
|
|
417
398
|
def test_map_reduce
|
418
|
-
|
419
|
-
|
399
|
+
Cfg.test << { "user_id" => 1 }
|
400
|
+
Cfg.test << { "user_id" => 2 }
|
420
401
|
m = "function() { emit(this.user_id, 1); }"
|
421
402
|
r = "function(k,vals) { return 1; }"
|
422
|
-
res =
|
403
|
+
res = Cfg.test.map_reduce(m, r, :out => 'foo');
|
423
404
|
assert res.find_one({"_id" => 1})
|
424
405
|
assert res.find_one({"_id" => 2})
|
425
406
|
end
|
426
407
|
|
427
408
|
def test_map_reduce_with_code_objects
|
428
|
-
|
429
|
-
|
409
|
+
Cfg.test << { "user_id" => 1 }
|
410
|
+
Cfg.test << { "user_id" => 2 }
|
430
411
|
m = Code.new("function() { emit(this.user_id, 1); }")
|
431
412
|
r = Code.new("function(k,vals) { return 1; }")
|
432
|
-
res =
|
413
|
+
res = Cfg.test.map_reduce(m, r, :out => 'foo');
|
433
414
|
assert res.find_one({"_id" => 1})
|
434
415
|
assert res.find_one({"_id" => 2})
|
435
416
|
end
|
436
417
|
|
437
418
|
def test_map_reduce_with_options
|
438
|
-
|
439
|
-
|
440
|
-
|
419
|
+
Cfg.test << { "user_id" => 1 }
|
420
|
+
Cfg.test << { "user_id" => 2 }
|
421
|
+
Cfg.test << { "user_id" => 3 }
|
441
422
|
m = Code.new("function() { emit(this.user_id, 1); }")
|
442
423
|
r = Code.new("function(k,vals) { return 1; }")
|
443
|
-
res =
|
424
|
+
res = Cfg.test.map_reduce(m, r, :query => {"user_id" => {"$gt" => 1}}, :out => 'foo');
|
444
425
|
assert_equal 2, res.count
|
445
426
|
assert res.find_one({"_id" => 2})
|
446
427
|
assert res.find_one({"_id" => 3})
|
447
428
|
end
|
448
429
|
|
449
430
|
def test_map_reduce_with_raw_response
|
450
|
-
|
451
|
-
|
452
|
-
|
431
|
+
Cfg.test << { "user_id" => 1 }
|
432
|
+
Cfg.test << { "user_id" => 2 }
|
433
|
+
Cfg.test << { "user_id" => 3 }
|
453
434
|
m = Code.new("function() { emit(this.user_id, 1); }")
|
454
435
|
r = Code.new("function(k,vals) { return 1; }")
|
455
|
-
res =
|
436
|
+
res = Cfg.test.map_reduce(m, r, :raw => true, :out => 'foo')
|
456
437
|
assert res["result"]
|
457
438
|
assert res["counts"]
|
458
439
|
assert res["timeMillis"]
|
459
440
|
end
|
460
441
|
|
461
442
|
def test_map_reduce_with_output_collection
|
462
|
-
|
463
|
-
|
464
|
-
|
443
|
+
Cfg.test << { "user_id" => 1 }
|
444
|
+
Cfg.test << { "user_id" => 2 }
|
445
|
+
Cfg.test << { "user_id" => 3 }
|
465
446
|
output_collection = "test-map-coll"
|
466
447
|
m = Code.new("function() { emit(this.user_id, 1); }")
|
467
448
|
r = Code.new("function(k,vals) { return 1; }")
|
468
|
-
res =
|
449
|
+
res = Cfg.test.map_reduce(m, r, :raw => true, :out => output_collection)
|
469
450
|
assert_equal output_collection, res["result"]
|
470
451
|
assert res["counts"]
|
471
452
|
assert res["timeMillis"]
|
472
453
|
end
|
473
454
|
|
474
|
-
if
|
455
|
+
if Cfg.version >= "1.8.0"
|
475
456
|
def test_map_reduce_with_collection_merge
|
476
|
-
|
477
|
-
|
457
|
+
Cfg.test << {:user_id => 1}
|
458
|
+
Cfg.test << {:user_id => 2}
|
478
459
|
output_collection = "test-map-coll"
|
479
460
|
m = Code.new("function() { emit(this.user_id, {count: 1}); }")
|
480
461
|
r = Code.new("function(k,vals) { var sum = 0;" +
|
481
462
|
" vals.forEach(function(v) { sum += v.count;} ); return {count: sum}; }")
|
482
|
-
res =
|
463
|
+
res = Cfg.test.map_reduce(m, r, :out => output_collection)
|
483
464
|
|
484
|
-
|
485
|
-
|
486
|
-
res =
|
465
|
+
Cfg.test.remove
|
466
|
+
Cfg.test << {:user_id => 3}
|
467
|
+
res = Cfg.test.map_reduce(m, r, :out => {:merge => output_collection})
|
487
468
|
assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 1}
|
488
469
|
|
489
|
-
|
490
|
-
|
491
|
-
res =
|
470
|
+
Cfg.test.remove
|
471
|
+
Cfg.test << {:user_id => 3}
|
472
|
+
res = Cfg.test.map_reduce(m, r, :out => {:reduce => output_collection})
|
492
473
|
assert res.find.to_a.any? {|doc| doc["_id"] == 3 && doc["value"]["count"] == 2}
|
493
474
|
|
494
475
|
assert_raises ArgumentError do
|
495
|
-
|
476
|
+
Cfg.test.map_reduce(m, r, :out => {:inline => 1})
|
496
477
|
end
|
497
478
|
|
498
|
-
|
479
|
+
Cfg.test.map_reduce(m, r, :raw => true, :out => {:inline => 1})
|
499
480
|
assert res["results"]
|
500
481
|
end
|
501
482
|
end
|
502
483
|
|
503
|
-
if
|
484
|
+
if Cfg.version > "1.3.0"
|
504
485
|
def test_find_and_modify
|
505
|
-
|
506
|
-
|
507
|
-
|
486
|
+
Cfg.test << { :a => 1, :processed => false }
|
487
|
+
Cfg.test << { :a => 2, :processed => false }
|
488
|
+
Cfg.test << { :a => 3, :processed => false }
|
508
489
|
|
509
|
-
|
490
|
+
Cfg.test.find_and_modify(:query => {}, :sort => [['a', -1]], :update => {"$set" => {:processed => true}})
|
510
491
|
|
511
|
-
assert
|
492
|
+
assert Cfg.test.find_one({:a => 3})['processed']
|
512
493
|
end
|
513
494
|
|
514
495
|
def test_find_and_modify_with_invalid_options
|
515
|
-
|
516
|
-
|
517
|
-
|
496
|
+
Cfg.test << { :a => 1, :processed => false }
|
497
|
+
Cfg.test << { :a => 2, :processed => false }
|
498
|
+
Cfg.test << { :a => 3, :processed => false }
|
518
499
|
|
519
500
|
assert_raises Mongo::OperationFailure do
|
520
|
-
|
501
|
+
Cfg.test.find_and_modify(:blimey => {})
|
521
502
|
end
|
522
503
|
end
|
523
504
|
end
|
524
505
|
|
525
|
-
if
|
506
|
+
if Cfg.version >= "1.3.5"
|
526
507
|
def test_coll_stats
|
527
|
-
|
528
|
-
|
529
|
-
stats =
|
530
|
-
assert_equal "#{
|
508
|
+
Cfg.test << {:n => 1}
|
509
|
+
Cfg.test.create_index("n")
|
510
|
+
stats = Cfg.test.stats
|
511
|
+
assert_equal "#{MONGO_TEST_DB}.test", stats['ns']
|
531
512
|
end
|
532
513
|
end
|
533
514
|
|
534
515
|
def test_saving_dates_pre_epoch
|
535
516
|
begin
|
536
|
-
|
537
|
-
assert_in_delta Time.utc(1600),
|
517
|
+
Cfg.test.save({'date' => Time.utc(1600)})
|
518
|
+
assert_in_delta Time.utc(1600), Cfg.test.find_one()["date"], 2
|
538
519
|
rescue ArgumentError
|
539
520
|
# See note in test_date_before_epoch (BSONTest)
|
540
521
|
end
|
541
522
|
end
|
542
523
|
|
543
524
|
def test_save_symbol_find_string
|
544
|
-
|
525
|
+
Cfg.test.save(:foo => :mike, :foo1 => 'mike')
|
545
526
|
|
546
|
-
assert_equal :mike,
|
547
|
-
assert_equal :mike,
|
548
|
-
assert_equal 'mike',
|
527
|
+
assert_equal :mike, Cfg.test.find_one(:foo => :mike)["foo"]
|
528
|
+
assert_equal :mike, Cfg.test.find_one("foo" => :mike)["foo"]
|
529
|
+
assert_equal 'mike', Cfg.test.find_one("foo" => :mike)["foo1"]
|
549
530
|
|
550
|
-
assert_equal :mike,
|
551
|
-
assert_equal :mike,
|
531
|
+
assert_equal :mike, Cfg.test.find_one(:foo => "mike")["foo"]
|
532
|
+
assert_equal :mike, Cfg.test.find_one("foo" => "mike")["foo"]
|
552
533
|
end
|
553
534
|
|
554
535
|
def test_limit_and_skip
|
555
536
|
10.times do |i|
|
556
|
-
|
537
|
+
Cfg.test.save(:foo => i)
|
557
538
|
end
|
558
539
|
|
559
|
-
assert_equal 5,
|
560
|
-
assert_equal nil,
|
540
|
+
assert_equal 5, Cfg.test.find({}, :skip => 5).next_document()["foo"]
|
541
|
+
assert_equal nil, Cfg.test.find({}, :skip => 10).next_document()
|
561
542
|
|
562
|
-
assert_equal 5,
|
543
|
+
assert_equal 5, Cfg.test.find({}, :limit => 5).to_a.length
|
563
544
|
|
564
|
-
assert_equal 3,
|
565
|
-
assert_equal 5,
|
545
|
+
assert_equal 3, Cfg.test.find({}, :skip => 3, :limit => 5).next_document()["foo"]
|
546
|
+
assert_equal 5, Cfg.test.find({}, :skip => 3, :limit => 5).to_a.length
|
566
547
|
end
|
567
548
|
|
568
549
|
def test_large_limit
|
569
550
|
2000.times do |i|
|
570
|
-
|
551
|
+
Cfg.test.insert("x" => i, "y" => "mongomongo" * 1000)
|
571
552
|
end
|
572
553
|
|
573
|
-
assert_equal 2000,
|
554
|
+
assert_equal 2000, Cfg.test.count
|
574
555
|
|
575
556
|
i = 0
|
576
557
|
y = 0
|
577
|
-
|
558
|
+
Cfg.test.find({}, :limit => 1900).each do |doc|
|
578
559
|
i += 1
|
579
560
|
y += doc["x"]
|
580
561
|
end
|
@@ -584,13 +565,13 @@ class TestCollection < MiniTest::Unit::TestCase
|
|
584
565
|
end
|
585
566
|
|
586
567
|
def test_small_limit
|
587
|
-
|
588
|
-
|
568
|
+
Cfg.test.insert("x" => "hello world")
|
569
|
+
Cfg.test.insert("x" => "goodbye world")
|
589
570
|
|
590
|
-
assert_equal 2,
|
571
|
+
assert_equal 2, Cfg.test.count
|
591
572
|
|
592
573
|
x = 0
|
593
|
-
|
574
|
+
Cfg.test.find({}, :limit => 1).each do |doc|
|
594
575
|
x += 1
|
595
576
|
assert_equal "hello world", doc["x"]
|
596
577
|
end
|
@@ -601,126 +582,128 @@ class TestCollection < MiniTest::Unit::TestCase
|
|
601
582
|
def test_find_with_transformer
|
602
583
|
klass = Struct.new(:id, :a)
|
603
584
|
transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
|
604
|
-
cursor =
|
585
|
+
cursor = Cfg.test.find({}, :transformer => transformer)
|
605
586
|
assert_equal(transformer, cursor.transformer)
|
606
587
|
end
|
607
588
|
|
608
589
|
def test_find_one_with_transformer
|
609
590
|
klass = Struct.new(:id, :a)
|
610
591
|
transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
|
611
|
-
id =
|
612
|
-
doc =
|
592
|
+
id = Cfg.test.insert('a' => 1)
|
593
|
+
doc = Cfg.test.find_one(id, :transformer => transformer)
|
613
594
|
assert_instance_of(klass, doc)
|
614
595
|
end
|
615
596
|
|
616
597
|
def test_ensure_index
|
617
|
-
|
618
|
-
|
619
|
-
assert_equal 1,
|
598
|
+
Cfg.test.drop_indexes
|
599
|
+
Cfg.test.insert("x" => "hello world")
|
600
|
+
assert_equal 1, Cfg.test.index_information.keys.count #default index
|
620
601
|
|
621
|
-
|
622
|
-
assert_equal 2,
|
623
|
-
assert
|
602
|
+
Cfg.test.ensure_index([["x", Mongo::DESCENDING]], {})
|
603
|
+
assert_equal 2, Cfg.test.index_information.keys.count
|
604
|
+
assert Cfg.test.index_information.keys.include? "x_-1"
|
624
605
|
|
625
|
-
|
626
|
-
assert
|
606
|
+
Cfg.test.ensure_index([["x", Mongo::ASCENDING]])
|
607
|
+
assert Cfg.test.index_information.keys.include? "x_1"
|
627
608
|
|
628
|
-
|
629
|
-
assert
|
609
|
+
Cfg.test.ensure_index([["type", 1], ["date", -1]])
|
610
|
+
assert Cfg.test.index_information.keys.include? "type_1_date_-1"
|
630
611
|
|
631
|
-
|
632
|
-
assert_equal 3,
|
633
|
-
|
634
|
-
assert_equal 2,
|
612
|
+
Cfg.test.drop_index("x_1")
|
613
|
+
assert_equal 3, Cfg.test.index_information.keys.count
|
614
|
+
Cfg.test.drop_index("x_-1")
|
615
|
+
assert_equal 2, Cfg.test.index_information.keys.count
|
635
616
|
|
636
|
-
|
637
|
-
assert_equal 3,
|
638
|
-
assert
|
617
|
+
Cfg.test.ensure_index([["x", Mongo::DESCENDING]], {})
|
618
|
+
assert_equal 3, Cfg.test.index_information.keys.count
|
619
|
+
assert Cfg.test.index_information.keys.include? "x_-1"
|
639
620
|
|
640
621
|
# Make sure that drop_index expires cache properly
|
641
|
-
|
642
|
-
assert
|
643
|
-
|
644
|
-
assert
|
645
|
-
|
646
|
-
assert
|
647
|
-
|
622
|
+
Cfg.test.ensure_index([['a', 1]])
|
623
|
+
assert Cfg.test.index_information.keys.include?("a_1")
|
624
|
+
Cfg.test.drop_index("a_1")
|
625
|
+
assert !Cfg.test.index_information.keys.include?("a_1")
|
626
|
+
Cfg.test.ensure_index([['a', 1]])
|
627
|
+
assert Cfg.test.index_information.keys.include?("a_1")
|
628
|
+
Cfg.test.drop_index("a_1")
|
648
629
|
end
|
649
630
|
|
650
631
|
end
|
651
632
|
|
652
633
|
require 'minitest/spec'
|
653
634
|
|
635
|
+
describe "Collection" do
|
636
|
+
before do
|
637
|
+
Cfg.clear_all
|
638
|
+
end
|
639
|
+
|
654
640
|
describe "Grouping" do
|
655
641
|
before do
|
656
|
-
|
657
|
-
|
658
|
-
$test.save("b" => 1)
|
642
|
+
Cfg.test.save("a" => 1)
|
643
|
+
Cfg.test.save("b" => 1)
|
659
644
|
@initial = {"count" => 0}
|
660
645
|
@reduce_function = "function (obj, prev) { prev.count += inc_value; }"
|
661
646
|
@grp_opts = {:initial => @initial, :reduce => BSON::Code.new(@reduce_function, {"inc_value" => 1})}
|
662
647
|
end
|
663
648
|
|
664
649
|
it "should fail if missing required options" do
|
665
|
-
lambda {
|
666
|
-
lambda {
|
650
|
+
lambda { Cfg.test.group(:initial => {}) }.must_raise Mongo::MongoArgumentError
|
651
|
+
lambda { Cfg.test.group(:reduce => "foo") }.must_raise Mongo::MongoArgumentError
|
667
652
|
end
|
668
653
|
|
669
654
|
it "should group results using eval form" do
|
670
655
|
@grp_opts[:reduce] = BSON::Code.new(@reduce_function, {"inc_value" => 0.5})
|
671
|
-
|
656
|
+
Cfg.test.group( @grp_opts )[0]["count"].must_equal 1
|
672
657
|
|
673
658
|
@grp_opts[:reduce] = BSON::Code.new(@reduce_function, {"inc_value" => 1})
|
674
|
-
|
659
|
+
Cfg.test.group( @grp_opts )[0]["count"].must_equal 2
|
675
660
|
|
676
661
|
@grp_opts[:reduce] = BSON::Code.new(@reduce_function, {"inc_value" => 2})
|
677
|
-
|
662
|
+
Cfg.test.group( @grp_opts )[0]["count"].must_equal 4
|
678
663
|
end
|
679
664
|
|
680
665
|
it "should finalize grouped results" do
|
681
666
|
@grp_opts[:finalize] = "function(doc) {doc.f = doc.count + 200; }"
|
682
|
-
|
667
|
+
Cfg.test.group( @grp_opts )[0]["f"].must_equal 202
|
683
668
|
end
|
684
669
|
end
|
685
670
|
|
686
671
|
describe "Grouping with key" do
|
687
672
|
before do
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
$test.save("a" => 2, "pop" => 100)
|
673
|
+
Cfg.test.save("a" => 1, "pop" => 100)
|
674
|
+
Cfg.test.save("a" => 1, "pop" => 100)
|
675
|
+
Cfg.test.save("a" => 2, "pop" => 100)
|
676
|
+
Cfg.test.save("a" => 2, "pop" => 100)
|
693
677
|
@initial = {"count" => 0, "foo" => 1}
|
694
678
|
@reduce_function = "function (obj, prev) { prev.count += obj.pop; }"
|
695
679
|
end
|
696
680
|
|
697
681
|
it "should group" do
|
698
|
-
result =
|
682
|
+
result = Cfg.test.group(:key => ['a'], :initial => @initial, :reduce => @reduce_function)
|
699
683
|
true.must_equal result.all? { |r| r['count'] == 200 }
|
700
684
|
end
|
701
685
|
end
|
702
686
|
|
703
687
|
describe "Grouping with a key function" do
|
704
688
|
before do
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
$test.save("a" => 5)
|
689
|
+
Cfg.test.save("a" => 1)
|
690
|
+
Cfg.test.save("a" => 2)
|
691
|
+
Cfg.test.save("a" => 3)
|
692
|
+
Cfg.test.save("a" => 4)
|
693
|
+
Cfg.test.save("a" => 5)
|
711
694
|
@initial = {"count" => 0}
|
712
695
|
@keyf = "function (doc) { if(doc.a % 2 == 0) { return {even: true}; } else {return {odd: true}} };"
|
713
696
|
@reduce = "function (obj, prev) { prev.count += 1; }"
|
714
697
|
end
|
715
698
|
|
716
699
|
it "should group results" do
|
717
|
-
results =
|
700
|
+
results = Cfg.test.group(:keyf => @keyf, :initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
|
718
701
|
true.must_equal results[0]['even'] && results[0]['count'] == 2.0
|
719
702
|
true.must_equal results[1]['odd'] && results[1]['count'] == 3.0
|
720
703
|
end
|
721
704
|
|
722
705
|
it "should group filtered results" do
|
723
|
-
results =
|
706
|
+
results = Cfg.test.group(:keyf => @keyf, :cond => {:a => {'$ne' => 2}},
|
724
707
|
:initial => @initial, :reduce => @reduce).sort {|a, b| a['count'] <=> b['count']}
|
725
708
|
true.must_equal results[0]['even'] && results[0]['count'] == 1.0
|
726
709
|
true.must_equal results[1]['odd'] && results[1]['count'] == 3.0
|
@@ -729,8 +712,7 @@ require 'minitest/spec'
|
|
729
712
|
|
730
713
|
describe "A collection with two records" do
|
731
714
|
before do
|
732
|
-
@collection =
|
733
|
-
@collection.remove
|
715
|
+
@collection = Cfg.db.collection('test-collection')
|
734
716
|
@collection.insert({:name => "Jones"})
|
735
717
|
@collection.insert({:name => "Smith"})
|
736
718
|
end
|
@@ -757,8 +739,7 @@ require 'minitest/spec'
|
|
757
739
|
|
758
740
|
describe "Drop index " do
|
759
741
|
before do
|
760
|
-
|
761
|
-
@collection = $db.collection('test-collection')
|
742
|
+
@collection = Cfg.db.collection('test-collection')
|
762
743
|
end
|
763
744
|
|
764
745
|
it "should drop an index" do
|
@@ -792,10 +773,10 @@ require 'minitest/spec'
|
|
792
773
|
|
793
774
|
describe "Creating indexes " do
|
794
775
|
before do
|
795
|
-
|
796
|
-
|
797
|
-
@collection
|
798
|
-
@geo =
|
776
|
+
Cfg.db.drop_collection('test-collection')
|
777
|
+
@collection = Cfg.db.collection('test-collection')
|
778
|
+
@collection.insert({:aaa => 1})
|
779
|
+
@geo = Cfg.db.collection('geo')
|
799
780
|
end
|
800
781
|
|
801
782
|
it "should create index using symbols" do
|
@@ -817,15 +798,18 @@ require 'minitest/spec'
|
|
817
798
|
|
818
799
|
it "should create a unique index" do
|
819
800
|
@collection.create_index([['a', Mongo::ASCENDING]], :unique => true)
|
820
|
-
|
801
|
+
info = @collection.index_information['a_1']
|
802
|
+
assert info
|
803
|
+
assert info['unique']
|
821
804
|
end
|
822
805
|
|
823
806
|
it "should drop duplicates" do
|
824
807
|
@collection.insert({:a => 1})
|
825
808
|
@collection.insert({:a => 1})
|
826
|
-
assert_equal 2, @collection.
|
809
|
+
assert_equal 2, @collection.count(:query => {:a => 1})
|
827
810
|
@collection.create_index([['a', Mongo::ASCENDING]], :unique => true, :dropDups => true)
|
828
811
|
assert_equal 1, @collection.find({:a => 1}).count
|
812
|
+
assert_equal 1, @collection.find({:a => 1}).count
|
829
813
|
end
|
830
814
|
|
831
815
|
it "should drop duplicates with ruby-like drop_dups key" do
|
@@ -845,7 +829,7 @@ require 'minitest/spec'
|
|
845
829
|
end
|
846
830
|
|
847
831
|
it "should create an index in the background" do
|
848
|
-
if
|
832
|
+
if Cfg.version > '1.3.1'
|
849
833
|
@collection.create_index([['b', Mongo::ASCENDING]], :background => true)
|
850
834
|
assert @collection.index_information['b_1']['background'] == true
|
851
835
|
else
|
@@ -896,8 +880,8 @@ require 'minitest/spec'
|
|
896
880
|
|
897
881
|
# describe "Capped collections" do
|
898
882
|
# before do
|
899
|
-
#
|
900
|
-
# @capped =
|
883
|
+
# Cfg.db.drop_collection('log')
|
884
|
+
# @capped = Cfg.db.create_collection('log', :capped => true, :size => 1024)
|
901
885
|
|
902
886
|
# 10.times { |n| @capped.insert({:n => n}) }
|
903
887
|
# end
|
@@ -913,7 +897,7 @@ require 'minitest/spec'
|
|
913
897
|
# end
|
914
898
|
|
915
899
|
# it "should fail tailable cursor on a non-capped collection" do
|
916
|
-
# col =
|
900
|
+
# col = Cfg.db['regular-collection']
|
917
901
|
# col.insert({:a => 1000})
|
918
902
|
# tail = Cursor.new(col, :tailable => true, :order => [['$natural', 1]])
|
919
903
|
# assert_raises OperationFailure do
|
@@ -931,3 +915,4 @@ require 'minitest/spec'
|
|
931
915
|
# assert tail.next_document
|
932
916
|
# end
|
933
917
|
# end
|
918
|
+
end
|