mongo 2.16.3 → 2.17.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.md +1 -1
- data/lib/mongo/auth/aws/request.rb +0 -1
- data/lib/mongo/client.rb +4 -0
- data/lib/mongo/cluster/reapers/cursor_reaper.rb +26 -14
- data/lib/mongo/collection/view/aggregation.rb +62 -17
- data/lib/mongo/collection/view/builder/aggregation.rb +11 -13
- data/lib/mongo/collection/view/builder/map_reduce.rb +1 -1
- data/lib/mongo/collection/view/change_stream.rb +7 -3
- data/lib/mongo/collection/view/iterable.rb +2 -3
- data/lib/mongo/collection/view/map_reduce.rb +2 -0
- data/lib/mongo/collection/view/readable.rb +24 -1
- data/lib/mongo/collection/view/writable.rb +23 -0
- data/lib/mongo/collection.rb +21 -1
- data/lib/mongo/cursor/kill_spec.rb +19 -2
- data/lib/mongo/cursor.rb +5 -5
- data/lib/mongo/database/view.rb +4 -2
- data/lib/mongo/database.rb +6 -6
- data/lib/mongo/error/snapshot_session_invalid_server_version.rb +31 -0
- data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +30 -0
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/operation/delete/op_msg.rb +2 -1
- data/lib/mongo/operation/find/builder/command.rb +1 -0
- data/lib/mongo/operation/result.rb +6 -0
- data/lib/mongo/operation/shared/executable.rb +4 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +18 -2
- data/lib/mongo/operation/update/op_msg.rb +2 -1
- data/lib/mongo/server/description/features.rb +3 -1
- data/lib/mongo/server_selector/base.rb +26 -4
- data/lib/mongo/session.rb +19 -0
- data/lib/mongo/socket/ocsp_cache.rb +2 -3
- data/lib/mongo/socket.rb +1 -5
- data/lib/mongo/utils.rb +0 -6
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +1 -1
- data/spec/integration/read_preference_spec.rb +16 -12
- data/spec/mongo/cluster/cursor_reaper_spec.rb +22 -15
- data/spec/mongo/collection/view/aggregation_spec.rb +71 -95
- data/spec/mongo/collection/view/change_stream_spec.rb +1 -1
- data/spec/mongo/collection/view/map_reduce_spec.rb +14 -1
- data/spec/mongo/cursor_spec.rb +3 -2
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +24 -1
- data/spec/mongo/server_selector_spec.rb +136 -15
- data/spec/mongo/socket/ssl_spec.rb +26 -58
- data/spec/mongo/utils_spec.rb +0 -14
- data/spec/runners/crud/verifier.rb +1 -2
- data/spec/runners/unified/assertions.rb +3 -1
- data/spec/runners/unified/crud_operations.rb +77 -23
- data/spec/runners/unified/ddl_operations.rb +29 -1
- data/spec/runners/unified/entity_map.rb +3 -3
- data/spec/runners/unified/support_operations.rb +6 -1
- data/spec/runners/unified/test.rb +15 -3
- data/spec/spec_tests/data/crud_unified/aggregate-let.yml +138 -0
- data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +155 -0
- data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +151 -0
- data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +91 -0
- data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +89 -0
- data/spec/spec_tests/data/crud_unified/find-let.yml +71 -0
- data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +88 -0
- data/spec/spec_tests/data/crud_unified/findOneAndReplace-let.yml +94 -0
- data/spec/spec_tests/data/crud_unified/findOneAndUpdate-let.yml +96 -0
- data/spec/spec_tests/data/crud_unified/updateMany-let.yml +103 -0
- data/spec/spec_tests/data/crud_unified/updateOne-let.yml +98 -0
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Secondary.yml +4 -4
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +4 -4
- data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +2 -2
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +5 -5
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +5 -5
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
- data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/Sharded/SmallMaxStaleness.yml +2 -2
- data/spec/spec_tests/data/max_staleness/Single/SmallMaxStaleness.yml +1 -1
- data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -1
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +69 -0
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-server-error.yml +102 -0
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +258 -0
- data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +482 -0
- data/spec/spec_tests/sessions_unified_spec.rb +13 -0
- data.tar.gz.sig +0 -0
- metadata +36 -2
- metadata.gz.sig +0 -0
@@ -8,7 +8,9 @@ module Unified
|
|
8
8
|
def find(op)
|
9
9
|
collection = entities.get(:collection, op.use!('object'))
|
10
10
|
use_arguments(op) do |args|
|
11
|
-
opts = {
|
11
|
+
opts = {
|
12
|
+
let: args.use('let'),
|
13
|
+
}
|
12
14
|
if session = args.use('session')
|
13
15
|
opts[:session] = entities.get(:session, session)
|
14
16
|
end
|
@@ -29,7 +31,11 @@ module Unified
|
|
29
31
|
def count_documents(op)
|
30
32
|
collection = entities.get(:collection, op.use!('object'))
|
31
33
|
use_arguments(op) do |args|
|
32
|
-
|
34
|
+
opts = {}
|
35
|
+
if session = args.use('session')
|
36
|
+
opts[:session] = entities.get(:session, session)
|
37
|
+
end
|
38
|
+
collection.find(args.use!('filter')).count_documents(**opts)
|
33
39
|
end
|
34
40
|
end
|
35
41
|
|
@@ -47,7 +53,11 @@ module Unified
|
|
47
53
|
def distinct(op)
|
48
54
|
collection = entities.get(:collection, op.use!('object'))
|
49
55
|
use_arguments(op) do |args|
|
50
|
-
|
56
|
+
opts = {}
|
57
|
+
if session = args.use('session')
|
58
|
+
opts[:session] = entities.get(:session, session)
|
59
|
+
end
|
60
|
+
req = collection.find(args.use!('filter'), **opts).distinct(args.use!('fieldName'), **opts)
|
51
61
|
result = req.to_a
|
52
62
|
end
|
53
63
|
end
|
@@ -57,10 +67,15 @@ module Unified
|
|
57
67
|
use_arguments(op) do |args|
|
58
68
|
filter = args.use!('filter')
|
59
69
|
update = args.use!('update')
|
60
|
-
opts = {
|
70
|
+
opts = {
|
71
|
+
let: args.use('let'),
|
72
|
+
}
|
61
73
|
if return_document = args.use('returnDocument')
|
62
74
|
opts[:return_document] = return_document.downcase.to_sym
|
63
75
|
end
|
76
|
+
if session = args.use('session')
|
77
|
+
opts[:session] = entities.get(:session, session)
|
78
|
+
end
|
64
79
|
collection.find_one_and_update(filter, update, **opts)
|
65
80
|
end
|
66
81
|
end
|
@@ -70,7 +85,13 @@ module Unified
|
|
70
85
|
use_arguments(op) do |args|
|
71
86
|
filter = args.use!('filter')
|
72
87
|
update = args.use!('replacement')
|
73
|
-
|
88
|
+
opts = {
|
89
|
+
let: args.use('let'),
|
90
|
+
}
|
91
|
+
if session = args.use('session')
|
92
|
+
opts[:session] = entities.get(:session, session)
|
93
|
+
end
|
94
|
+
collection.find_one_and_replace(filter, update, **opts)
|
74
95
|
end
|
75
96
|
end
|
76
97
|
|
@@ -78,7 +99,13 @@ module Unified
|
|
78
99
|
collection = entities.get(:collection, op.use!('object'))
|
79
100
|
use_arguments(op) do |args|
|
80
101
|
filter = args.use!('filter')
|
81
|
-
|
102
|
+
opts = {
|
103
|
+
let: args.use('let'),
|
104
|
+
}
|
105
|
+
if session = args.use('session')
|
106
|
+
opts[:session] = entities.get(:session, session)
|
107
|
+
end
|
108
|
+
collection.find_one_and_delete(filter, **opts)
|
82
109
|
end
|
83
110
|
end
|
84
111
|
|
@@ -96,25 +123,37 @@ module Unified
|
|
96
123
|
def insert_many(op)
|
97
124
|
collection = entities.get(:collection, op.use!('object'))
|
98
125
|
use_arguments(op) do |args|
|
99
|
-
|
126
|
+
opts = {}
|
100
127
|
unless (ordered = args.use('ordered')).nil?
|
101
|
-
|
128
|
+
opts[:ordered] = ordered
|
129
|
+
end
|
130
|
+
if session = args.use('session')
|
131
|
+
opts[:session] = entities.get(:session, session)
|
102
132
|
end
|
103
|
-
collection.insert_many(args.use!('documents'), **
|
133
|
+
collection.insert_many(args.use!('documents'), **opts)
|
104
134
|
end
|
105
135
|
end
|
106
136
|
|
107
137
|
def update_one(op)
|
108
138
|
collection = entities.get(:collection, op.use!('object'))
|
109
139
|
use_arguments(op) do |args|
|
110
|
-
|
140
|
+
opts = {
|
141
|
+
let: args.use('let'),
|
142
|
+
}
|
143
|
+
if session = args.use('session')
|
144
|
+
opts[:session] = entities.get(:session, session)
|
145
|
+
end
|
146
|
+
collection.update_one(args.use!('filter'), args.use!('update'), **opts)
|
111
147
|
end
|
112
148
|
end
|
113
149
|
|
114
150
|
def update_many(op)
|
115
151
|
collection = entities.get(:collection, op.use!('object'))
|
116
152
|
use_arguments(op) do |args|
|
117
|
-
|
153
|
+
opts = {
|
154
|
+
let: args.use('let'),
|
155
|
+
}
|
156
|
+
collection.update_many(args.use!('filter'), args.use!('update'), **opts)
|
118
157
|
end
|
119
158
|
end
|
120
159
|
|
@@ -132,14 +171,23 @@ module Unified
|
|
132
171
|
def delete_one(op)
|
133
172
|
collection = entities.get(:collection, op.use!('object'))
|
134
173
|
use_arguments(op) do |args|
|
135
|
-
|
174
|
+
opts = {
|
175
|
+
let: args.use('let'),
|
176
|
+
}
|
177
|
+
if session = args.use('session')
|
178
|
+
opts[:session] = entities.get(:session, session)
|
179
|
+
end
|
180
|
+
collection.delete_one(args.use!('filter'), **opts)
|
136
181
|
end
|
137
182
|
end
|
138
183
|
|
139
184
|
def delete_many(op)
|
140
185
|
collection = entities.get(:collection, op.use!('object'))
|
141
186
|
use_arguments(op) do |args|
|
142
|
-
|
187
|
+
opts = {
|
188
|
+
let: args.use('let'),
|
189
|
+
}
|
190
|
+
collection.delete_many(args.use!('filter'), **opts)
|
143
191
|
end
|
144
192
|
end
|
145
193
|
|
@@ -157,6 +205,22 @@ module Unified
|
|
157
205
|
end
|
158
206
|
end
|
159
207
|
|
208
|
+
def aggregate(op)
|
209
|
+
obj = entities.get_any(op.use!('object'))
|
210
|
+
args = op.use!('arguments')
|
211
|
+
pipeline = args.use!('pipeline')
|
212
|
+
opts = {
|
213
|
+
let: args.use('let'),
|
214
|
+
}
|
215
|
+
if session = args.use('session')
|
216
|
+
opts[:session] = entities.get(:session, session)
|
217
|
+
end
|
218
|
+
unless args.empty?
|
219
|
+
raise NotImplementedError, "Unhandled spec keys: #{args} in #{test_spec}"
|
220
|
+
end
|
221
|
+
obj.aggregate(pipeline, **opts).to_a
|
222
|
+
end
|
223
|
+
|
160
224
|
private
|
161
225
|
|
162
226
|
def convert_bulk_write_spec(spec)
|
@@ -192,15 +256,5 @@ module Unified
|
|
192
256
|
end
|
193
257
|
{Utils.underscore(op) =>out}
|
194
258
|
end
|
195
|
-
|
196
|
-
def aggregate(op)
|
197
|
-
obj = entities.get_any(op.use!('object'))
|
198
|
-
args = op.use!('arguments')
|
199
|
-
pipeline = args.use!('pipeline')
|
200
|
-
unless args.empty?
|
201
|
-
raise NotImplementedError, "Unhandled spec keys: #{test_spec}"
|
202
|
-
end
|
203
|
-
obj.aggregate(pipeline).to_a
|
204
|
-
end
|
205
259
|
end
|
206
260
|
end
|
@@ -7,7 +7,13 @@ module Unified
|
|
7
7
|
|
8
8
|
def list_databases(op)
|
9
9
|
client = entities.get(:client, op.use!('object'))
|
10
|
-
|
10
|
+
use_arguments(op) do |args|
|
11
|
+
opts = {}
|
12
|
+
if session = args.use('session')
|
13
|
+
opts[:session] = entities.get(:session, session)
|
14
|
+
end
|
15
|
+
client.list_databases({}, false, **opts)
|
16
|
+
end
|
11
17
|
end
|
12
18
|
|
13
19
|
def create_collection(op)
|
@@ -28,6 +34,17 @@ module Unified
|
|
28
34
|
end
|
29
35
|
end
|
30
36
|
|
37
|
+
def list_collections(op)
|
38
|
+
database = entities.get(:database, op.use!('object'))
|
39
|
+
use_arguments(op) do |args|
|
40
|
+
opts = {}
|
41
|
+
if session = args.use('session')
|
42
|
+
opts[:session] = entities.get(:session, session)
|
43
|
+
end
|
44
|
+
database.list_collections(**opts)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
31
48
|
def drop_collection(op)
|
32
49
|
database = entities.get(:database, op.use!('object'))
|
33
50
|
use_arguments(op) do |args|
|
@@ -58,6 +75,17 @@ module Unified
|
|
58
75
|
assert_collection_exists(op, false)
|
59
76
|
end
|
60
77
|
|
78
|
+
def list_indexes(op)
|
79
|
+
collection = entities.get(:collection, op.use!('object'))
|
80
|
+
use_arguments(op) do |args|
|
81
|
+
opts = {}
|
82
|
+
if session = args.use('session')
|
83
|
+
opts[:session] = entities.get(:session, session)
|
84
|
+
end
|
85
|
+
collection.indexes(**opts).to_a
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
61
89
|
def create_index(op)
|
62
90
|
collection = entities.get(:collection, op.use!('object'))
|
63
91
|
use_arguments(op) do |args|
|
@@ -3,6 +3,8 @@
|
|
3
3
|
|
4
4
|
module Unified
|
5
5
|
class EntityMap
|
6
|
+
extend Forwardable
|
7
|
+
|
6
8
|
def initialize
|
7
9
|
@map = {}
|
8
10
|
end
|
@@ -35,8 +37,6 @@ module Unified
|
|
35
37
|
raise Error::EntityMissing, "There is no #{id} known"
|
36
38
|
end
|
37
39
|
|
38
|
-
|
39
|
-
@map[type]
|
40
|
-
end
|
40
|
+
def_delegators :@map, :[], :fetch
|
41
41
|
end
|
42
42
|
end
|
@@ -160,13 +160,24 @@ module Unified
|
|
160
160
|
end
|
161
161
|
when 'database'
|
162
162
|
client = entities.get(:client, spec.use!('client'))
|
163
|
-
|
163
|
+
opts = Utils.snakeize_hash(spec.use('databaseOptions') || {})
|
164
|
+
.merge(database: spec.use!('databaseName'))
|
165
|
+
if opts.key?(:read_preference)
|
166
|
+
opts[:read] = opts.delete(:read_preference)
|
167
|
+
if opts[:read].key?(:max_staleness_seconds)
|
168
|
+
opts[:read][:max_staleness] = opts[:read].delete(:max_staleness_seconds)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
client.with(opts).database
|
164
172
|
when 'collection'
|
165
173
|
database = entities.get(:database, spec.use!('database'))
|
166
174
|
# TODO verify
|
167
175
|
opts = Utils.snakeize_hash(spec.use('collectionOptions') || {})
|
168
176
|
if opts.key?(:read_preference)
|
169
177
|
opts[:read] = opts.delete(:read_preference)
|
178
|
+
if opts[:read].key?(:max_staleness_seconds)
|
179
|
+
opts[:read][:max_staleness] = opts[:read].delete(:max_staleness_seconds)
|
180
|
+
end
|
170
181
|
end
|
171
182
|
database[spec.use!('collectionName'), opts]
|
172
183
|
when 'bucket'
|
@@ -195,7 +206,8 @@ module Unified
|
|
195
206
|
def set_initial_data
|
196
207
|
@spec['initialData']&.each do |entity_spec|
|
197
208
|
spec = UsingHash[entity_spec]
|
198
|
-
collection = root_authorized_client.
|
209
|
+
collection = root_authorized_client.with(write_concern: {w: :majority}).
|
210
|
+
use(spec.use!('databaseName'))[spec.use!('collectionName')]
|
199
211
|
collection.drop
|
200
212
|
docs = spec.use!('documents')
|
201
213
|
if docs.any?
|
@@ -268,7 +280,7 @@ module Unified
|
|
268
280
|
end
|
269
281
|
if expected_error = op.use('expectError')
|
270
282
|
begin
|
271
|
-
|
283
|
+
public_send(method_name, op)
|
272
284
|
rescue Mongo::Error, BSON::String::IllegalKey => e
|
273
285
|
if expected_error.use('isClientError')
|
274
286
|
# isClientError doesn't actually mean a client error.
|
@@ -0,0 +1,138 @@
|
|
1
|
+
description: "aggregate-let"
|
2
|
+
|
3
|
+
schemaVersion: "1.4"
|
4
|
+
|
5
|
+
createEntities:
|
6
|
+
- client:
|
7
|
+
id: &client0 client0
|
8
|
+
observeEvents: [ commandStartedEvent ]
|
9
|
+
- database:
|
10
|
+
id: &database0 database0
|
11
|
+
client: *client0
|
12
|
+
databaseName: &database0Name crud-tests
|
13
|
+
- collection:
|
14
|
+
id: &collection0 collection0
|
15
|
+
database: *database0
|
16
|
+
collectionName: &collection0Name coll0
|
17
|
+
- collection:
|
18
|
+
id: &collection1 collection1
|
19
|
+
database: *database0
|
20
|
+
collectionName: &collection1Name coll1
|
21
|
+
|
22
|
+
initialData: &initialData
|
23
|
+
- collectionName: *collection0Name
|
24
|
+
databaseName: *database0Name
|
25
|
+
documents:
|
26
|
+
- { _id: 1 }
|
27
|
+
- collectionName: *collection1Name
|
28
|
+
databaseName: *database0Name
|
29
|
+
documents: [ ]
|
30
|
+
|
31
|
+
tests:
|
32
|
+
- description: "Aggregate with let option"
|
33
|
+
runOnRequirements:
|
34
|
+
- minServerVersion: "5.0"
|
35
|
+
operations:
|
36
|
+
- name: aggregate
|
37
|
+
object: *collection0
|
38
|
+
arguments:
|
39
|
+
pipeline: &pipeline0
|
40
|
+
# $match takes a query expression, so $expr is necessary to utilize
|
41
|
+
# an aggregate expression context and access "let" variables.
|
42
|
+
- $match: { $expr: { $eq: ["$_id", "$$id"] } }
|
43
|
+
- $project: { _id: 0, x: "$$x", y: "$$y", rand: "$$rand" }
|
44
|
+
# Values in "let" must be constant or closed expressions that do not
|
45
|
+
# depend on document values. This test demonstrates a basic constant
|
46
|
+
# value, a value wrapped with $literal (to avoid expression parsing),
|
47
|
+
# and a closed expression (e.g. $rand).
|
48
|
+
let: &let0
|
49
|
+
id: 1
|
50
|
+
x: foo
|
51
|
+
y: { $literal: "$bar" }
|
52
|
+
rand: { $rand: {} }
|
53
|
+
expectResult:
|
54
|
+
- { x: "foo", y: "$bar", rand: { $$type: "double" } }
|
55
|
+
expectEvents:
|
56
|
+
- client: *client0
|
57
|
+
events:
|
58
|
+
- commandStartedEvent:
|
59
|
+
command:
|
60
|
+
aggregate: *collection0Name
|
61
|
+
pipeline: *pipeline0
|
62
|
+
let: *let0
|
63
|
+
|
64
|
+
- description: "Aggregate with let option unsupported (server-side error)"
|
65
|
+
runOnRequirements:
|
66
|
+
- minServerVersion: "2.6.0"
|
67
|
+
maxServerVersion: "4.4.99"
|
68
|
+
operations:
|
69
|
+
- name: aggregate
|
70
|
+
object: *collection0
|
71
|
+
arguments:
|
72
|
+
pipeline: &pipeline1
|
73
|
+
- $match: { _id: 1 }
|
74
|
+
let: &let1
|
75
|
+
x: foo
|
76
|
+
expectError:
|
77
|
+
# Older server versions may not report an error code, but the error
|
78
|
+
# message is consistent between 2.6.x and 4.4.x server versions.
|
79
|
+
errorContains: "unrecognized field 'let'"
|
80
|
+
isClientError: false
|
81
|
+
expectEvents:
|
82
|
+
- client: *client0
|
83
|
+
events:
|
84
|
+
- commandStartedEvent:
|
85
|
+
command:
|
86
|
+
aggregate: *collection0Name
|
87
|
+
pipeline: *pipeline1
|
88
|
+
let: *let1
|
89
|
+
|
90
|
+
- description: "Aggregate to collection with let option"
|
91
|
+
runOnRequirements:
|
92
|
+
- minServerVersion: "5.0"
|
93
|
+
serverless: "forbid"
|
94
|
+
operations:
|
95
|
+
- name: aggregate
|
96
|
+
object: *collection0
|
97
|
+
arguments:
|
98
|
+
pipeline: &pipeline2
|
99
|
+
- $match: { $expr: { $eq: ["$_id", "$$id"] } }
|
100
|
+
- $project: { _id: 1 }
|
101
|
+
- $out: *collection1Name
|
102
|
+
let: &let2
|
103
|
+
id: 1
|
104
|
+
expectEvents:
|
105
|
+
- client: *client0
|
106
|
+
events:
|
107
|
+
- commandStartedEvent:
|
108
|
+
command:
|
109
|
+
aggregate: *collection0Name
|
110
|
+
pipeline: *pipeline2
|
111
|
+
let: *let2
|
112
|
+
outcome:
|
113
|
+
- collectionName: *collection1Name
|
114
|
+
databaseName: *database0Name
|
115
|
+
documents:
|
116
|
+
- { _id: 1 }
|
117
|
+
|
118
|
+
- description: "Aggregate to collection with let option unsupported (server-side error)"
|
119
|
+
runOnRequirements:
|
120
|
+
- minServerVersion: "2.6.0"
|
121
|
+
maxServerVersion: "4.4.99"
|
122
|
+
operations:
|
123
|
+
- name: aggregate
|
124
|
+
object: *collection0
|
125
|
+
arguments:
|
126
|
+
pipeline: *pipeline2
|
127
|
+
let: *let2
|
128
|
+
expectError:
|
129
|
+
errorContains: "unrecognized field 'let'"
|
130
|
+
isClientError: false
|
131
|
+
expectEvents:
|
132
|
+
- client: *client0
|
133
|
+
events:
|
134
|
+
- commandStartedEvent:
|
135
|
+
command:
|
136
|
+
aggregate: *collection0Name
|
137
|
+
pipeline: *pipeline2
|
138
|
+
let: *let2
|
@@ -0,0 +1,155 @@
|
|
1
|
+
description: aggregate-write-readPreference
|
2
|
+
|
3
|
+
schemaVersion: '1.4'
|
4
|
+
|
5
|
+
runOnRequirements:
|
6
|
+
# 3.6+ non-standalone is needed to utilize $readPreference in OP_MSG
|
7
|
+
- minServerVersion: "3.6"
|
8
|
+
topologies: [ replicaset, sharded, load-balanced ]
|
9
|
+
|
10
|
+
_yamlAnchors:
|
11
|
+
readConcern: &readConcern
|
12
|
+
level: &readConcernLevel "local"
|
13
|
+
writeConcern: &writeConcern
|
14
|
+
w: &writeConcernW 1
|
15
|
+
|
16
|
+
createEntities:
|
17
|
+
- client:
|
18
|
+
id: &client0 client0
|
19
|
+
observeEvents:
|
20
|
+
- commandStartedEvent
|
21
|
+
# Used to test that read and write concerns are still inherited
|
22
|
+
uriOptions:
|
23
|
+
readConcernLevel: *readConcernLevel
|
24
|
+
w: *writeConcernW
|
25
|
+
- database:
|
26
|
+
id: &database0 database0
|
27
|
+
client: *client0
|
28
|
+
databaseName: &database0Name db0
|
29
|
+
- collection:
|
30
|
+
id: &collection0 collection0
|
31
|
+
database: *database0
|
32
|
+
collectionName: &collection0Name coll0
|
33
|
+
collectionOptions:
|
34
|
+
readPreference: &readPreference
|
35
|
+
# secondaryPreferred is specified for compatibility with clusters that
|
36
|
+
# may not have a secondary (e.g. each shard is only a primary).
|
37
|
+
mode: secondaryPreferred
|
38
|
+
# maxStalenessSeconds is specified to ensure that drivers forward the
|
39
|
+
# read preference to mongos or a load balancer. That would not be the
|
40
|
+
# case with only secondaryPreferred.
|
41
|
+
maxStalenessSeconds: 600
|
42
|
+
- collection:
|
43
|
+
id: &collection1 collection1
|
44
|
+
database: *database0
|
45
|
+
collectionName: &collection1Name coll1
|
46
|
+
|
47
|
+
initialData:
|
48
|
+
- collectionName: *collection0Name
|
49
|
+
databaseName: *database0Name
|
50
|
+
documents:
|
51
|
+
- { _id: 1, x: 11 }
|
52
|
+
- { _id: 2, x: 22 }
|
53
|
+
- { _id: 3, x: 33 }
|
54
|
+
- collectionName: *collection1Name
|
55
|
+
databaseName: *database0Name
|
56
|
+
documents: []
|
57
|
+
|
58
|
+
tests:
|
59
|
+
- description: "Aggregate with $out includes read preference for 5.0+ server"
|
60
|
+
runOnRequirements:
|
61
|
+
- minServerVersion: "5.0"
|
62
|
+
serverless: "forbid"
|
63
|
+
operations:
|
64
|
+
- object: *collection0
|
65
|
+
name: aggregate
|
66
|
+
arguments:
|
67
|
+
pipeline: &outPipeline
|
68
|
+
- { $match: { _id: { $gt: 1 } } }
|
69
|
+
- { $sort: { x: 1 } }
|
70
|
+
- { $out: *collection1Name }
|
71
|
+
expectEvents:
|
72
|
+
- client: *client0
|
73
|
+
events:
|
74
|
+
- commandStartedEvent:
|
75
|
+
command:
|
76
|
+
aggregate: *collection0Name
|
77
|
+
pipeline: *outPipeline
|
78
|
+
$readPreference: *readPreference
|
79
|
+
readConcern: *readConcern
|
80
|
+
writeConcern: *writeConcern
|
81
|
+
outcome: &outcome
|
82
|
+
- collectionName: *collection1Name
|
83
|
+
databaseName: *database0Name
|
84
|
+
documents:
|
85
|
+
- { _id: 2, x: 22 }
|
86
|
+
- { _id: 3, x: 33 }
|
87
|
+
|
88
|
+
- description: "Aggregate with $out omits read preference for pre-5.0 server"
|
89
|
+
runOnRequirements:
|
90
|
+
# MongoDB 4.2 introduced support for read concerns and write stages.
|
91
|
+
# Pre-4.2 servers may allow a "local" read concern anyway, but some
|
92
|
+
# drivers may avoid inheriting a client-level read concern for pre-4.2.
|
93
|
+
- minServerVersion: "4.2"
|
94
|
+
maxServerVersion: "4.4.99"
|
95
|
+
serverless: "forbid"
|
96
|
+
operations:
|
97
|
+
- object: *collection0
|
98
|
+
name: aggregate
|
99
|
+
arguments:
|
100
|
+
pipeline: *outPipeline
|
101
|
+
expectEvents:
|
102
|
+
- client: *client0
|
103
|
+
events:
|
104
|
+
- commandStartedEvent:
|
105
|
+
command:
|
106
|
+
aggregate: *collection0Name
|
107
|
+
pipeline: *outPipeline
|
108
|
+
$readPreference: { $$exists: false }
|
109
|
+
readConcern: *readConcern
|
110
|
+
writeConcern: *writeConcern
|
111
|
+
outcome: *outcome
|
112
|
+
|
113
|
+
- description: "Aggregate with $merge includes read preference for 5.0+ server"
|
114
|
+
runOnRequirements:
|
115
|
+
- minServerVersion: "5.0"
|
116
|
+
operations:
|
117
|
+
- object: *collection0
|
118
|
+
name: aggregate
|
119
|
+
arguments:
|
120
|
+
pipeline: &mergePipeline
|
121
|
+
- { $match: { _id: { $gt: 1 } } }
|
122
|
+
- { $sort: { x: 1 } }
|
123
|
+
- { $merge: { into: *collection1Name } }
|
124
|
+
expectEvents:
|
125
|
+
- client: *client0
|
126
|
+
events:
|
127
|
+
- commandStartedEvent:
|
128
|
+
command:
|
129
|
+
aggregate: *collection0Name
|
130
|
+
pipeline: *mergePipeline
|
131
|
+
$readPreference: *readPreference
|
132
|
+
readConcern: *readConcern
|
133
|
+
writeConcern: *writeConcern
|
134
|
+
outcome: *outcome
|
135
|
+
|
136
|
+
- description: "Aggregate with $merge omits read preference for pre-5.0 server"
|
137
|
+
runOnRequirements:
|
138
|
+
- minServerVersion: "4.2"
|
139
|
+
maxServerVersion: "4.4.99"
|
140
|
+
operations:
|
141
|
+
- object: *collection0
|
142
|
+
name: aggregate
|
143
|
+
arguments:
|
144
|
+
pipeline: *mergePipeline
|
145
|
+
expectEvents:
|
146
|
+
- client: *client0
|
147
|
+
events:
|
148
|
+
- commandStartedEvent:
|
149
|
+
command:
|
150
|
+
aggregate: *collection0Name
|
151
|
+
pipeline: *mergePipeline
|
152
|
+
$readPreference: { $$exists: false }
|
153
|
+
readConcern: *readConcern
|
154
|
+
writeConcern: *writeConcern
|
155
|
+
outcome: *outcome
|