mongo 1.1.5 → 1.2.rc0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +1 -1
- data/docs/HISTORY.md +8 -0
- data/docs/REPLICA_SETS.md +8 -12
- data/lib/mongo.rb +3 -1
- data/lib/mongo/collection.rb +32 -28
- data/lib/mongo/connection.rb +61 -42
- data/lib/mongo/cursor.rb +13 -13
- data/lib/mongo/db.rb +30 -30
- data/lib/mongo/repl_set_connection.rb +17 -3
- data/lib/mongo/util/pool.rb +3 -3
- data/lib/mongo/util/uri_parser.rb +119 -11
- data/test/bson/bson_test.rb +24 -2
- data/test/collection_test.rb +34 -6
- data/test/connection_test.rb +35 -0
- data/test/replica_sets/connect_test.rb +2 -1
- data/test/replica_sets/connection_string_test.rb +32 -0
- data/test/replica_sets/query_secondaries.rb +4 -0
- data/test/replica_sets/replication_ack_test.rb +2 -0
- data/test/replica_sets/rs_test_helper.rb +9 -11
- data/test/unit/collection_test.rb +0 -1
- data/test/unit/connection_test.rb +4 -4
- data/test/unit/repl_set_connection_test.rb +0 -10
- data/test/unit/safe_test.rb +2 -2
- data/test/uri_test.rb +75 -0
- metadata +20 -14
data/lib/mongo/db.rb
CHANGED
@@ -56,33 +56,33 @@ module Mongo
|
|
56
56
|
|
57
57
|
# Instances of DB are normally obtained by calling Mongo#db.
|
58
58
|
#
|
59
|
-
# @param [String]
|
59
|
+
# @param [String] name the database name.
|
60
60
|
# @param [Mongo::Connection] connection a connection object pointing to MongoDB. Note
|
61
61
|
# that databases are usually instantiated via the Connection class. See the examples below.
|
62
62
|
#
|
63
|
-
# @option
|
63
|
+
# @option opts [Boolean] :strict (False) If true, collections must exist to be accessed and must
|
64
64
|
# not exist to be created. See DB#collection and DB#create_collection.
|
65
65
|
#
|
66
|
-
# @option
|
66
|
+
# @option opts [Object, #create_pk(doc)] :pk (Mongo::ObjectId) A primary key factory object,
|
67
67
|
# which should take a hash and return a hash which merges the original hash with any primary key
|
68
68
|
# fields the factory wishes to inject. (NOTE: if the object already has a primary key,
|
69
69
|
# the factory should not inject a new key).
|
70
70
|
#
|
71
|
-
# @option
|
71
|
+
# @option opts [Boolean, Hash] :safe (false) Set the default safe-mode options
|
72
72
|
# propogated to Collection objects instantiated off of this DB. If no
|
73
73
|
# value is provided, the default value set on this instance's Connection object will be used. This
|
74
74
|
# default can be overridden upon instantiation of any collection by explicity setting a :safe value
|
75
75
|
# on initialization
|
76
|
-
# @option
|
76
|
+
# @option opts [Integer] :cache_time (300) Set the time that all ensure_index calls should cache the command.
|
77
77
|
#
|
78
78
|
# @core databases constructor_details
|
79
|
-
def initialize(
|
80
|
-
@name = Mongo::Support.validate_db_name(
|
79
|
+
def initialize(name, connection, opts={})
|
80
|
+
@name = Mongo::Support.validate_db_name(name)
|
81
81
|
@connection = connection
|
82
|
-
@strict =
|
83
|
-
@pk_factory =
|
84
|
-
@safe =
|
85
|
-
@cache_time =
|
82
|
+
@strict = opts[:strict]
|
83
|
+
@pk_factory = opts[:pk]
|
84
|
+
@safe = opts.fetch(:safe, @connection.safe)
|
85
|
+
@cache_time = opts[:cache_time] || 300 #5 minutes.
|
86
86
|
end
|
87
87
|
|
88
88
|
# Authenticate with the given username and password. Note that mongod
|
@@ -208,8 +208,8 @@ module Mongo
|
|
208
208
|
#
|
209
209
|
# @return [Array<Mongo::Collection>]
|
210
210
|
def collections
|
211
|
-
collection_names.map do |
|
212
|
-
Collection.new(
|
211
|
+
collection_names.map do |name|
|
212
|
+
Collection.new(name, self)
|
213
213
|
end
|
214
214
|
end
|
215
215
|
|
@@ -223,7 +223,7 @@ module Mongo
|
|
223
223
|
def collections_info(coll_name=nil)
|
224
224
|
selector = {}
|
225
225
|
selector[:name] = full_collection_name(coll_name) if coll_name
|
226
|
-
Cursor.new(Collection.new(
|
226
|
+
Cursor.new(Collection.new(SYSTEM_NAMESPACE_COLLECTION, self), :selector => selector)
|
227
227
|
end
|
228
228
|
|
229
229
|
# Create a collection.
|
@@ -233,52 +233,52 @@ module Mongo
|
|
233
233
|
#
|
234
234
|
# @param [String] name the name of the new collection.
|
235
235
|
#
|
236
|
-
# @option
|
236
|
+
# @option opts [Boolean] :capped (False) created a capped collection.
|
237
237
|
#
|
238
|
-
# @option
|
238
|
+
# @option opts [Integer] :size (Nil) If +capped+ is +true+, specifies the maximum number of
|
239
239
|
# bytes for the capped collection. If +false+, specifies the number of bytes allocated
|
240
240
|
# for the initial extent of the collection.
|
241
241
|
#
|
242
|
-
# @option
|
242
|
+
# @option opts [Integer] :max (Nil) If +capped+ is +true+, indicates the maximum number of records
|
243
243
|
# in a capped collection.
|
244
244
|
#
|
245
245
|
# @raise [MongoDBError] raised under two conditions: either we're in +strict+ mode and the collection
|
246
246
|
# already exists or collection creation fails on the server.
|
247
247
|
#
|
248
248
|
# @return [Mongo::Collection]
|
249
|
-
def create_collection(name,
|
249
|
+
def create_collection(name, opts={})
|
250
250
|
# Does the collection already exist?
|
251
251
|
if collection_names.include?(name)
|
252
252
|
if strict?
|
253
253
|
raise MongoDBError, "Collection #{name} already exists. Currently in strict mode."
|
254
254
|
else
|
255
|
-
return Collection.new(
|
255
|
+
return Collection.new(name, self)
|
256
256
|
end
|
257
257
|
end
|
258
258
|
|
259
259
|
# Create a new collection.
|
260
260
|
oh = BSON::OrderedHash.new
|
261
261
|
oh[:create] = name
|
262
|
-
doc = command(oh.merge(
|
263
|
-
return Collection.new(
|
262
|
+
doc = command(oh.merge(opts || {}))
|
263
|
+
return Collection.new(name, self, :pk => @pk_factory) if ok?(doc)
|
264
264
|
raise MongoDBError, "Error creating collection: #{doc.inspect}"
|
265
265
|
end
|
266
266
|
|
267
267
|
# Get a collection by name.
|
268
268
|
#
|
269
269
|
# @param [String] name the collection name.
|
270
|
-
# @param [Hash]
|
270
|
+
# @param [Hash] opts any valid options that can me passed to Collection#new.
|
271
271
|
#
|
272
272
|
# @raise [MongoDBError] if collection does not already exist and we're in +strict+ mode.
|
273
273
|
#
|
274
274
|
# @return [Mongo::Collection]
|
275
|
-
def collection(name,
|
275
|
+
def collection(name, opts={})
|
276
276
|
if strict? && !collection_names.include?(name)
|
277
277
|
raise Mongo::MongoDBError, "Collection #{name} doesn't exist. Currently in strict mode."
|
278
278
|
else
|
279
|
-
|
280
|
-
|
281
|
-
Collection.new(
|
279
|
+
opts[:safe] = opts.fetch(:safe, @safe)
|
280
|
+
opts.merge!(:pk => @pk_factory) unless opts[:pk]
|
281
|
+
Collection.new(name, self, opts)
|
282
282
|
end
|
283
283
|
end
|
284
284
|
alias_method :[], :collection
|
@@ -403,7 +403,7 @@ module Mongo
|
|
403
403
|
def drop_index(collection_name, index_name)
|
404
404
|
oh = BSON::OrderedHash.new
|
405
405
|
oh[:deleteIndexes] = collection_name
|
406
|
-
oh[:index] = index_name
|
406
|
+
oh[:index] = index_name.to_s
|
407
407
|
doc = command(oh, :check_response => false)
|
408
408
|
ok?(doc) || raise(MongoDBError, "Error with drop_index command: #{doc.inspect}")
|
409
409
|
end
|
@@ -418,7 +418,7 @@ module Mongo
|
|
418
418
|
def index_information(collection_name)
|
419
419
|
sel = {:ns => full_collection_name(collection_name)}
|
420
420
|
info = {}
|
421
|
-
Cursor.new(Collection.new(
|
421
|
+
Cursor.new(Collection.new(SYSTEM_INDEX_COLLECTION, self), :selector => sel).each do |index|
|
422
422
|
info[index['name']] = index
|
423
423
|
end
|
424
424
|
info
|
@@ -558,7 +558,7 @@ module Mongo
|
|
558
558
|
#
|
559
559
|
# @return [Array] a list of documents containing profiling information.
|
560
560
|
def profiling_info
|
561
|
-
Cursor.new(Collection.new(
|
561
|
+
Cursor.new(Collection.new(SYSTEM_PROFILE_COLLECTION, self), :selector => {}).to_a
|
562
562
|
end
|
563
563
|
|
564
564
|
# Validate a named collection.
|
@@ -581,7 +581,7 @@ module Mongo
|
|
581
581
|
private
|
582
582
|
|
583
583
|
def system_command_collection
|
584
|
-
Collection.new(
|
584
|
+
Collection.new(SYSTEM_COMMAND_COLLECTION, self)
|
585
585
|
end
|
586
586
|
end
|
587
587
|
end
|
@@ -32,6 +32,8 @@ module Mongo
|
|
32
32
|
# @param [Array] args A list of host-port pairs ending with a hash containing any options. See
|
33
33
|
# the examples below for exactly how to use the constructor.
|
34
34
|
#
|
35
|
+
# @option options [String] :rs_name (nil) The name of the replica set to connect to. You
|
36
|
+
# can use this option to verify that you're connecting to the right replica set.
|
35
37
|
# @option options [Boolean, Hash] :safe (false) Set the default safe-mode options
|
36
38
|
# propogated to DB objects instantiated off of this Connection. This
|
37
39
|
# default can be overridden upon instantiation of any DB by explicity setting a :safe value
|
@@ -48,8 +50,10 @@ module Mongo
|
|
48
50
|
# @example Connect to a replica set and provide two seed nodes:
|
49
51
|
# ReplSetConnection.new(['localhost', 30000], ['localhost', 30001])
|
50
52
|
#
|
51
|
-
# @example Connect to a replica set providing two seed nodes and
|
52
|
-
#
|
53
|
+
# @example Connect to a replica set providing two seed nodes and ensuring a connection to the replica set named 'prod':
|
54
|
+
# ReplSetConnection.new(['localhost', 30000], ['localhost', 30001], :rs_name => 'prod')
|
55
|
+
#
|
56
|
+
# @example Connect to a replica set providing two seed nodes and allowing reads from a secondary node:
|
53
57
|
# ReplSetConnection.new(['localhost', 30000], ['localhost', 30001], :read_secondary => true)
|
54
58
|
#
|
55
59
|
# @see http://api.mongodb.org/ruby/current/file.REPLICA_SETS.html Replica sets in Ruby
|
@@ -111,7 +115,9 @@ module Mongo
|
|
111
115
|
|
112
116
|
pick_secondary_for_read if @read_secondary
|
113
117
|
|
114
|
-
if
|
118
|
+
if connected?
|
119
|
+
BSON::BSON_CODER.update_max_bson_size(self)
|
120
|
+
else
|
115
121
|
if @secondary_pools.empty?
|
116
122
|
raise ConnectionFailure, "Failed to connect any given host:port"
|
117
123
|
else
|
@@ -124,6 +130,14 @@ module Mongo
|
|
124
130
|
@nodes_to_try.length > 0
|
125
131
|
end
|
126
132
|
|
133
|
+
# Determine whether we're reading from a primary node. If false,
|
134
|
+
# this connection connects to a secondary node and @read_secondaries is true.
|
135
|
+
#
|
136
|
+
# @return [Boolean]
|
137
|
+
def read_primary?
|
138
|
+
!@read_pool || @read_pool.length.zero?
|
139
|
+
end
|
140
|
+
|
127
141
|
# Close the connection to the database.
|
128
142
|
def close
|
129
143
|
super
|
data/lib/mongo/util/pool.rb
CHANGED
@@ -22,14 +22,14 @@ module Mongo
|
|
22
22
|
|
23
23
|
# Create a new pool of connections.
|
24
24
|
#
|
25
|
-
def initialize(connection, host, port,
|
25
|
+
def initialize(connection, host, port, opts={})
|
26
26
|
@connection = connection
|
27
27
|
|
28
28
|
@host, @port = host, port
|
29
29
|
|
30
30
|
# Pool size and timeout.
|
31
|
-
@size =
|
32
|
-
@timeout =
|
31
|
+
@size = opts[:size] || 1
|
32
|
+
@timeout = opts[:timeout] || 5.0
|
33
33
|
|
34
34
|
# Mutex for synchronizing pool access
|
35
35
|
@connection_mutex = Mutex.new
|
@@ -17,28 +17,99 @@
|
|
17
17
|
# ++
|
18
18
|
|
19
19
|
module Mongo
|
20
|
-
|
20
|
+
class URIParser
|
21
21
|
|
22
22
|
DEFAULT_PORT = 27017
|
23
23
|
MONGODB_URI_MATCHER = /(([-_.\w\d]+):([-_\w\d]+)@)?([-.\w\d]+)(:([\w\d]+))?(\/([-\d\w]+))?/
|
24
24
|
MONGODB_URI_SPEC = "mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/database]"
|
25
|
+
SPEC_ATTRS = [:nodes, :auths]
|
26
|
+
OPT_ATTRS = [:connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync]
|
25
27
|
|
26
|
-
|
28
|
+
OPT_VALID = {:connect => lambda {|arg| ['direct', 'replicaset'].include?(arg)},
|
29
|
+
:replicaset => lambda {|arg| arg.length > 0},
|
30
|
+
:slaveok => lambda {|arg| ['true', 'false'].include?(arg)},
|
31
|
+
:safe => lambda {|arg| ['true', 'false'].include?(arg)},
|
32
|
+
:w => lambda {|arg| arg =~ /^\d+$/ },
|
33
|
+
:wtimeout => lambda {|arg| arg =~ /^\d+$/ },
|
34
|
+
:fsync => lambda {|arg| ['true', 'false'].include?(arg)}
|
35
|
+
}
|
36
|
+
|
37
|
+
OPT_ERR = {:connect => "must be 'direct' or 'replicaset'",
|
38
|
+
:replicaset => "must be a string containing the name of the replica set to connect to",
|
39
|
+
:slaveok => "must be 'true' or 'false'",
|
40
|
+
:safe => "must be 'true' or 'false'",
|
41
|
+
:w => "must be an integer specifying number of nodes to replica to",
|
42
|
+
:wtimeout => "must be an integer specifying milliseconds",
|
43
|
+
:fsync => "must be 'true' or 'false'"
|
44
|
+
}
|
45
|
+
|
46
|
+
OPT_CONV = {:connect => lambda {|arg| arg},
|
47
|
+
:replicaset => lambda {|arg| arg},
|
48
|
+
:slaveok => lambda {|arg| arg == 'true' ? true : false},
|
49
|
+
:safe => lambda {|arg| arg == 'true' ? true : false},
|
50
|
+
:w => lambda {|arg| arg.to_i},
|
51
|
+
:wtimeout => lambda {|arg| arg.to_i},
|
52
|
+
:fsync => lambda {|arg| arg == 'true' ? true : false}
|
53
|
+
}
|
54
|
+
|
55
|
+
attr_reader :nodes, :auths, :connect, :replicaset, :slaveok, :safe, :w, :wtimeout, :fsync
|
27
56
|
|
28
57
|
# Parse a MongoDB URI. This method is used by Connection.from_uri.
|
29
58
|
# Returns an array of nodes and an array of db authorizations, if applicable.
|
30
59
|
#
|
31
|
-
# @
|
32
|
-
def
|
60
|
+
# @core connections
|
61
|
+
def initialize(string)
|
33
62
|
if string =~ /^mongodb:\/\//
|
34
63
|
string = string[10..-1]
|
35
64
|
else
|
36
65
|
raise MongoArgumentError, "MongoDB URI must match this spec: #{MONGODB_URI_SPEC}"
|
37
66
|
end
|
38
67
|
|
39
|
-
|
40
|
-
|
41
|
-
|
68
|
+
hosts, opts = string.split('?')
|
69
|
+
parse_hosts(hosts)
|
70
|
+
parse_options(opts)
|
71
|
+
configure_connect
|
72
|
+
end
|
73
|
+
|
74
|
+
def connection_options
|
75
|
+
opts = {}
|
76
|
+
|
77
|
+
if (@w || @wtimeout || @fsync) && !@safe
|
78
|
+
raise MongoArgumentError, "Safe must be true if w, wtimeout, or fsync is specified"
|
79
|
+
end
|
80
|
+
|
81
|
+
if @safe
|
82
|
+
if @w || @wtimeout || @fsync
|
83
|
+
safe_opts = {}
|
84
|
+
safe_opts[:w] = @w if @w
|
85
|
+
safe_opts[:wtimeout] = @wtimeout if @wtimeout
|
86
|
+
safe_opts[:fsync] = @fsync if @fsync
|
87
|
+
else
|
88
|
+
safe_opts = true
|
89
|
+
end
|
90
|
+
|
91
|
+
opts[:safe] = safe_opts
|
92
|
+
end
|
93
|
+
|
94
|
+
if @slaveok
|
95
|
+
if @connect == 'direct'
|
96
|
+
opts[:slave_ok] = true
|
97
|
+
else
|
98
|
+
opts[:read_secondary] = true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
opts[:rs_name] = @replicaset if @replicaset
|
103
|
+
|
104
|
+
opts
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def parse_hosts(hosts)
|
110
|
+
@nodes = []
|
111
|
+
@auths = []
|
112
|
+
specs = hosts.split(',')
|
42
113
|
specs.each do |spec|
|
43
114
|
matches = MONGODB_URI_MATCHER.match(spec)
|
44
115
|
if !matches
|
@@ -52,8 +123,8 @@ module Mongo
|
|
52
123
|
if !(port.to_s =~ /^\d+$/)
|
53
124
|
raise MongoArgumentError, "Invalid port #{port}; port must be specified as digits."
|
54
125
|
end
|
55
|
-
port
|
56
|
-
db
|
126
|
+
port = port.to_i
|
127
|
+
db = matches[8]
|
57
128
|
|
58
129
|
if uname && pwd && db
|
59
130
|
auths << {'db_name' => db, 'username' => uname, 'password' => pwd}
|
@@ -62,10 +133,47 @@ module Mongo
|
|
62
133
|
"and db if any one of these is specified."
|
63
134
|
end
|
64
135
|
|
65
|
-
nodes << [host, port]
|
136
|
+
@nodes << [host, port]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# This method uses the lambdas defined in OPT_VALID and OPT_CONV to validate
|
141
|
+
# and convert the given options.
|
142
|
+
def parse_options(opts)
|
143
|
+
return unless opts
|
144
|
+
separator = opts.include?('&') ? '&' : ';'
|
145
|
+
opts.split(separator).each do |attr|
|
146
|
+
key, value = attr.split('=')
|
147
|
+
key = key.to_sym
|
148
|
+
value = value.strip.downcase
|
149
|
+
if !OPT_ATTRS.include?(key)
|
150
|
+
raise MongoArgumentError, "Invalid Mongo URI option #{key}"
|
151
|
+
end
|
152
|
+
|
153
|
+
if OPT_VALID[key].call(value)
|
154
|
+
instance_variable_set("@#{key}", OPT_CONV[key].call(value))
|
155
|
+
else
|
156
|
+
raise MongoArgumentError, "Invalid value for #{key}: #{OPT_ERR[key]}"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def configure_connect
|
162
|
+
if @nodes.length > 1 && !@connect
|
163
|
+
@connect = 'replicaset'
|
66
164
|
end
|
67
165
|
|
68
|
-
|
166
|
+
if !@connect
|
167
|
+
if @nodes.length > 1
|
168
|
+
@connect = 'replicaset'
|
169
|
+
else
|
170
|
+
@connect = 'direct'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
if @connect == 'direct' && @replicaset
|
175
|
+
raise MongoArgumentError, "If specifying a replica set name, please also specify that connect=replicaset"
|
176
|
+
end
|
69
177
|
end
|
70
178
|
end
|
71
179
|
end
|
data/test/bson/bson_test.rb
CHANGED
@@ -67,13 +67,26 @@ class BSONTest < Test::Unit::TestCase
|
|
67
67
|
assert_doc_pass(doc)
|
68
68
|
end
|
69
69
|
|
70
|
-
def
|
71
|
-
doc = {'name' => 'a' *
|
70
|
+
def test_limit_max_bson_size
|
71
|
+
doc = {'name' => 'a' * BSON_CODER.max_bson_size}
|
72
72
|
assert_raise InvalidDocument do
|
73
73
|
assert @encoder.serialize(doc)
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
+
def test_max_bson_size
|
78
|
+
assert BSON_CODER.max_bson_size >= BSON::DEFAULT_MAX_BSON_SIZE
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_update_max_bson_size
|
82
|
+
require 'ostruct'
|
83
|
+
mock_conn = OpenStruct.new
|
84
|
+
size = 7 * 1024 * 1024
|
85
|
+
mock_conn.max_bson_size = size
|
86
|
+
assert_equal size, BSON_CODER.update_max_bson_size(mock_conn)
|
87
|
+
assert_equal size, BSON_CODER.max_bson_size
|
88
|
+
end
|
89
|
+
|
77
90
|
def test_round_trip
|
78
91
|
doc = {'doc' => 123}
|
79
92
|
@encoder.deserialize(@encoder.serialize(doc))
|
@@ -200,6 +213,15 @@ class BSONTest < Test::Unit::TestCase
|
|
200
213
|
assert_doc_pass(doc)
|
201
214
|
end
|
202
215
|
|
216
|
+
def test_array_keys
|
217
|
+
doc = {'doc' => [1, 2, 'a', 'b']}
|
218
|
+
bson = @encoder.serialize(doc).to_a
|
219
|
+
assert_equal 48, bson[14]
|
220
|
+
assert_equal 49, bson[21]
|
221
|
+
assert_equal 50, bson[28]
|
222
|
+
assert_equal 51, bson[37]
|
223
|
+
end
|
224
|
+
|
203
225
|
def test_regex
|
204
226
|
doc = {'doc' => /foobar/i}
|
205
227
|
assert_doc_pass(doc)
|
data/test/collection_test.rb
CHANGED
@@ -32,11 +32,11 @@ class TestCollection < Test::Unit::TestCase
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def test_pk_factory_on_collection
|
35
|
-
@coll = Collection.new(
|
35
|
+
@coll = Collection.new('foo', @@db, TestPK)
|
36
36
|
assert_equal TestPK, @coll.pk_factory
|
37
37
|
|
38
38
|
|
39
|
-
@coll2 = Collection.new(
|
39
|
+
@coll2 = Collection.new('foo', @@db, :pk => TestPK)
|
40
40
|
assert_equal TestPK, @coll2.pk_factory
|
41
41
|
end
|
42
42
|
|
@@ -417,7 +417,7 @@ class TestCollection < Test::Unit::TestCase
|
|
417
417
|
|
418
418
|
m = "function() { emit(this.user_id, 1); }"
|
419
419
|
r = "function(k,vals) { return 1; }"
|
420
|
-
res = @@test.map_reduce(m, r);
|
420
|
+
res = @@test.map_reduce(m, r, :out => 'foo');
|
421
421
|
assert res.find_one({"_id" => 1})
|
422
422
|
assert res.find_one({"_id" => 2})
|
423
423
|
end
|
@@ -428,7 +428,7 @@ class TestCollection < Test::Unit::TestCase
|
|
428
428
|
|
429
429
|
m = Code.new("function() { emit(this.user_id, 1); }")
|
430
430
|
r = Code.new("function(k,vals) { return 1; }")
|
431
|
-
res = @@test.map_reduce(m, r);
|
431
|
+
res = @@test.map_reduce(m, r, :out => 'foo');
|
432
432
|
assert res.find_one({"_id" => 1})
|
433
433
|
assert res.find_one({"_id" => 2})
|
434
434
|
end
|
@@ -441,7 +441,7 @@ class TestCollection < Test::Unit::TestCase
|
|
441
441
|
|
442
442
|
m = Code.new("function() { emit(this.user_id, 1); }")
|
443
443
|
r = Code.new("function(k,vals) { return 1; }")
|
444
|
-
res = @@test.map_reduce(m, r, :query => {"user_id" => {"$gt" => 1}});
|
444
|
+
res = @@test.map_reduce(m, r, :query => {"user_id" => {"$gt" => 1}}, :out => 'foo');
|
445
445
|
assert_equal 2, res.count
|
446
446
|
assert res.find_one({"_id" => 2})
|
447
447
|
assert res.find_one({"_id" => 3})
|
@@ -450,7 +450,7 @@ class TestCollection < Test::Unit::TestCase
|
|
450
450
|
def test_map_reduce_with_raw_response
|
451
451
|
m = Code.new("function() { emit(this.user_id, 1); }")
|
452
452
|
r = Code.new("function(k,vals) { return 1; }")
|
453
|
-
res = @@test.map_reduce(m, r, :raw => true)
|
453
|
+
res = @@test.map_reduce(m, r, :raw => true, :out => 'foo')
|
454
454
|
assert res["result"]
|
455
455
|
assert res["counts"]
|
456
456
|
assert res["timeMillis"]
|
@@ -600,6 +600,23 @@ class TestCollection < Test::Unit::TestCase
|
|
600
600
|
@@test.drop_index("a_1")
|
601
601
|
end
|
602
602
|
|
603
|
+
def test_ensure_index_timeout
|
604
|
+
@@db.cache_time = 2
|
605
|
+
coll = @@db['ensure_test']
|
606
|
+
coll.expects(:generate_indexes).twice
|
607
|
+
coll.ensure_index([['a', 1]])
|
608
|
+
|
609
|
+
# These will be cached
|
610
|
+
coll.ensure_index([['a', 1]])
|
611
|
+
coll.ensure_index([['a', 1]])
|
612
|
+
coll.ensure_index([['a', 1]])
|
613
|
+
coll.ensure_index([['a', 1]])
|
614
|
+
|
615
|
+
sleep(3)
|
616
|
+
# This won't be, so generate_indexes will be called twice
|
617
|
+
coll.ensure_index([['a', 1]])
|
618
|
+
end
|
619
|
+
|
603
620
|
context "Grouping" do
|
604
621
|
setup do
|
605
622
|
@@test.remove
|
@@ -693,6 +710,17 @@ class TestCollection < Test::Unit::TestCase
|
|
693
710
|
@geo = @@db.collection('geo')
|
694
711
|
end
|
695
712
|
|
713
|
+
should "create index using symbols" do
|
714
|
+
@collection.create_index :foo, :name => :bar
|
715
|
+
@geo.create_index :goo, :name => :baz
|
716
|
+
assert @collection.index_information['bar']
|
717
|
+
@collection.drop_index :bar
|
718
|
+
assert_nil @collection.index_information['bar']
|
719
|
+
assert @geo.index_information['baz']
|
720
|
+
@geo.drop_index(:baz)
|
721
|
+
assert_nil @geo.index_information['baz']
|
722
|
+
end
|
723
|
+
|
696
724
|
should "create a geospatial index" do
|
697
725
|
@geo.save({'loc' => [-100, 100]})
|
698
726
|
@geo.create_index([['loc', Mongo::GEO2D]])
|