mongo 2.1.2 → 2.2.0.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +10 -3
- data/Rakefile +1 -7
- data/lib/csasl/csasl.bundle +0 -0
- data/lib/mongo/auth/user/view.rb +1 -1
- data/lib/mongo/bulk_write.rb +7 -1
- data/lib/mongo/client.rb +17 -15
- data/lib/mongo/cluster.rb +4 -2
- data/lib/mongo/collection.rb +36 -2
- data/lib/mongo/collection/view.rb +24 -21
- data/lib/mongo/collection/view/aggregation.rb +5 -42
- data/lib/mongo/collection/view/builder.rb +20 -0
- data/lib/mongo/collection/view/builder/aggregation.rb +98 -0
- data/lib/mongo/collection/view/builder/find_command.rb +111 -0
- data/lib/mongo/collection/view/builder/flags.rb +62 -0
- data/lib/mongo/collection/view/builder/map_reduce.rb +134 -0
- data/lib/mongo/collection/view/builder/modifiers.rb +80 -0
- data/lib/mongo/collection/view/builder/op_query.rb +83 -0
- data/lib/mongo/collection/view/explainable.rb +15 -0
- data/lib/mongo/collection/view/immutable.rb +5 -12
- data/lib/mongo/collection/view/iterable.rb +24 -2
- data/lib/mongo/collection/view/map_reduce.rb +18 -27
- data/lib/mongo/collection/view/readable.rb +70 -112
- data/lib/mongo/collection/view/writable.rb +23 -7
- data/lib/mongo/cursor.rb +76 -25
- data/lib/mongo/cursor/builder.rb +18 -0
- data/lib/mongo/cursor/builder/get_more_command.rb +71 -0
- data/lib/mongo/cursor/builder/kill_cursors_command.rb +62 -0
- data/lib/mongo/cursor/builder/op_get_more.rb +61 -0
- data/lib/mongo/cursor/builder/op_kill_cursors.rb +56 -0
- data/lib/mongo/database.rb +2 -2
- data/lib/mongo/database/view.rb +9 -5
- data/lib/mongo/dbref.rb +3 -3
- data/lib/mongo/error.rb +1 -0
- data/lib/mongo/error/invalid_write_concern.rb +35 -0
- data/lib/mongo/grid/file/chunk.rb +2 -2
- data/lib/mongo/index/view.rb +5 -2
- data/lib/mongo/operation.rb +1 -0
- data/lib/mongo/operation/commands.rb +2 -0
- data/lib/mongo/operation/commands/aggregate.rb +39 -45
- data/lib/mongo/operation/commands/aggregate/result.rb +54 -68
- data/lib/mongo/operation/commands/collections_info.rb +38 -36
- data/lib/mongo/operation/commands/collections_info/result.rb +17 -15
- data/lib/mongo/operation/commands/command.rb +24 -22
- data/lib/mongo/operation/commands/find.rb +27 -0
- data/lib/mongo/operation/commands/find/result.rb +62 -0
- data/lib/mongo/operation/commands/get_more.rb +27 -0
- data/lib/mongo/operation/commands/get_more/result.rb +62 -0
- data/lib/mongo/operation/commands/indexes.rb +41 -39
- data/lib/mongo/operation/commands/list_collections.rb +25 -31
- data/lib/mongo/operation/commands/list_collections/result.rb +63 -81
- data/lib/mongo/operation/commands/list_indexes.rb +27 -35
- data/lib/mongo/operation/commands/list_indexes/result.rb +67 -85
- data/lib/mongo/operation/commands/map_reduce.rb +29 -37
- data/lib/mongo/operation/commands/map_reduce/result.rb +85 -88
- data/lib/mongo/operation/commands/parallel_scan.rb +29 -33
- data/lib/mongo/operation/commands/parallel_scan/result.rb +34 -42
- data/lib/mongo/operation/commands/user_query.rb +40 -38
- data/lib/mongo/operation/commands/users_info.rb +24 -29
- data/lib/mongo/operation/commands/users_info/result.rb +13 -11
- data/lib/mongo/operation/object_id_generator.rb +36 -0
- data/lib/mongo/operation/result.rb +30 -0
- data/lib/mongo/operation/specifiable.rb +35 -1
- data/lib/mongo/operation/write/bulk/bulkable.rb +4 -3
- data/lib/mongo/operation/write/bulk/delete/result.rb +18 -25
- data/lib/mongo/operation/write/bulk/legacy_mergable.rb +2 -2
- data/lib/mongo/operation/write/command/delete.rb +3 -2
- data/lib/mongo/operation/write/command/insert.rb +4 -2
- data/lib/mongo/operation/write/command/update.rb +6 -3
- data/lib/mongo/operation/write/gle.rb +2 -1
- data/lib/mongo/operation/write/idable.rb +19 -2
- data/lib/mongo/options/mapper.rb +22 -0
- data/lib/mongo/protocol/bit_vector.rb +3 -3
- data/lib/mongo/protocol/delete.rb +15 -5
- data/lib/mongo/protocol/get_more.rb +10 -5
- data/lib/mongo/protocol/insert.rb +1 -6
- data/lib/mongo/protocol/kill_cursors.rb +14 -1
- data/lib/mongo/protocol/message.rb +32 -8
- data/lib/mongo/protocol/serializers.rb +15 -16
- data/lib/mongo/protocol/update.rb +35 -12
- data/lib/mongo/server/connectable.rb +3 -1
- data/lib/mongo/server/connection.rb +5 -5
- data/lib/mongo/server/description.rb +8 -2
- data/lib/mongo/server/description/features.rb +2 -1
- data/lib/mongo/server/monitor.rb +1 -12
- data/lib/mongo/server/monitor/connection.rb +30 -26
- data/lib/mongo/server_selector/selectable.rb +21 -4
- data/lib/mongo/uri.rb +2 -0
- data/lib/mongo/version.rb +1 -1
- data/lib/mongo/write_concern.rb +21 -6
- data/mongo.gemspec +1 -2
- data/spec/mongo/bulk_write/ordered_combiner_spec.rb +13 -0
- data/spec/mongo/bulk_write_spec.rb +58 -0
- data/spec/mongo/client_spec.rb +6 -4
- data/spec/mongo/collection/view/builder/find_command_spec.rb +167 -0
- data/spec/mongo/collection/view/builder/flags_spec.rb +106 -0
- data/spec/mongo/collection/view/builder/modifiers_spec.rb +210 -0
- data/spec/mongo/collection/view/builder/op_query_spec.rb +154 -0
- data/spec/mongo/collection/view/explainable_spec.rb +1 -2
- data/spec/mongo/collection/view/immutable_spec.rb +3 -52
- data/spec/mongo/collection/view/map_reduce_spec.rb +12 -12
- data/spec/mongo/collection/view/readable_spec.rb +86 -80
- data/spec/mongo/collection/view_spec.rb +109 -703
- data/spec/mongo/collection_spec.rb +594 -11
- data/spec/mongo/command_monitoring_spec.rb +40 -27
- data/spec/mongo/cursor/builder/get_more_command_spec.rb +160 -0
- data/spec/mongo/cursor/builder/op_get_more_spec.rb +52 -0
- data/spec/mongo/cursor_spec.rb +10 -60
- data/spec/mongo/database_spec.rb +24 -3
- data/spec/mongo/dbref_spec.rb +4 -4
- data/spec/mongo/grid/file/chunk_spec.rb +1 -1
- data/spec/mongo/grid/fs_bucket_spec.rb +3 -3
- data/spec/mongo/index/view_spec.rb +41 -0
- data/spec/mongo/operation/{aggregate → commands/aggregate}/result_spec.rb +1 -1
- data/spec/mongo/operation/commands/aggregate_spec.rb +1 -1
- data/spec/mongo/operation/commands/collections_info_spec.rb +1 -1
- data/spec/mongo/operation/commands/command_spec.rb +1 -1
- data/spec/mongo/operation/commands/indexes_spec.rb +1 -1
- data/spec/mongo/operation/commands/map_reduce_spec.rb +1 -1
- data/spec/mongo/operation/write/command/delete_spec.rb +25 -0
- data/spec/mongo/operation/write/command/insert_spec.rb +25 -0
- data/spec/mongo/operation/write/command/update_spec.rb +25 -0
- data/spec/mongo/protocol/delete_spec.rb +4 -4
- data/spec/mongo/protocol/get_more_spec.rb +4 -4
- data/spec/mongo/protocol/insert_spec.rb +3 -3
- data/spec/mongo/protocol/kill_cursors_spec.rb +3 -3
- data/spec/mongo/protocol/query_spec.rb +7 -7
- data/spec/mongo/protocol/update_spec.rb +5 -5
- data/spec/mongo/server/description/features_spec.rb +25 -0
- data/spec/mongo/write_concern_spec.rb +126 -0
- data/spec/spec_helper.rb +9 -19
- data/spec/support/command_monitoring.rb +8 -0
- data/spec/support/command_monitoring/find.yml +53 -4
- data/spec/support/matchers.rb +1 -1
- data/spec/support/shared/protocol.rb +5 -5
- data/spec/support/travis.rb +1 -1
- metadata +43 -10
- metadata.gz.sig +0 -0
@@ -25,8 +25,7 @@ describe Mongo::Collection::View::Explainable do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'executes an explain' do
|
28
|
-
expect(explain[:cursor] == 'BasicCursor' ||
|
29
|
-
explain[:queryPlanner]).to be_truthy
|
28
|
+
expect(explain[:cursor] == 'BasicCursor' || explain[:queryPlanner]).to be_truthy
|
30
29
|
end
|
31
30
|
end
|
32
31
|
end
|
@@ -20,10 +20,10 @@ describe Mongo::Collection::View::Immutable do
|
|
20
20
|
|
21
21
|
describe '#configure' do
|
22
22
|
|
23
|
-
context 'when the options
|
23
|
+
context 'when the options have modifiers' do
|
24
24
|
|
25
25
|
let(:options) do
|
26
|
-
{
|
26
|
+
{ :max_time_ms => 500 }
|
27
27
|
end
|
28
28
|
|
29
29
|
let(:new_view) do
|
@@ -43,56 +43,7 @@ describe Mongo::Collection::View::Immutable do
|
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'sets the option' do
|
46
|
-
expect(new_view.projection).to eq(_id
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'creates a new modifiers document' do
|
50
|
-
expect(view.modifiers).not_to be(new_view.modifiers)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
describe '#configure_modifier' do
|
56
|
-
|
57
|
-
let(:new_view) do
|
58
|
-
view.sort('x' => Mongo::Index::ASCENDING)
|
59
|
-
end
|
60
|
-
|
61
|
-
context 'when the options does not have a modifiers document' do
|
62
|
-
|
63
|
-
it 'returns a new view' do
|
64
|
-
expect(view).not_to be(new_view)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'returns a new view with the modifiers document containing the option' do
|
68
|
-
expect(new_view.modifiers[:$orderby]).to eq({ 'x' => Mongo::Index::ASCENDING })
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
context 'when the options has a modifiers document' do
|
73
|
-
|
74
|
-
let(:options) do
|
75
|
-
{ modifiers: { :$maxTimeMS => 500 } }
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'returns a new view' do
|
79
|
-
expect(view).not_to be(new_view)
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'creates a new options hash' do
|
83
|
-
expect(view.options).not_to be(new_view.options)
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'keeps the fields already in the options hash and merges in the new one' do
|
87
|
-
expect(new_view.modifiers[:$maxTimeMS]).to eq(500)
|
88
|
-
end
|
89
|
-
|
90
|
-
it 'sets the new value in the new view modifier document' do
|
91
|
-
expect(new_view.modifiers[:$orderby]).to eq('x' => Mongo::Index::ASCENDING)
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'returns that value when the corresponding option method is called' do
|
95
|
-
expect(new_view.sort).to eq({ 'x' => Mongo::Index::ASCENDING })
|
46
|
+
expect(new_view.projection).to eq('_id' => 1)
|
96
47
|
end
|
97
48
|
|
98
49
|
it 'creates a new modifiers document' do
|
@@ -186,7 +186,7 @@ describe Mongo::Collection::View::MapReduce do
|
|
186
186
|
context 'when the selector is basic' do
|
187
187
|
|
188
188
|
let(:selector) do
|
189
|
-
{ name
|
189
|
+
{ 'name' => 'Berlin' }
|
190
190
|
end
|
191
191
|
|
192
192
|
it 'applies the selector to the map/reduce' do
|
@@ -203,7 +203,7 @@ describe Mongo::Collection::View::MapReduce do
|
|
203
203
|
context 'when the selector is advanced' do
|
204
204
|
|
205
205
|
let(:selector) do
|
206
|
-
{ :$query => { name
|
206
|
+
{ :$query => { 'name' => 'Berlin' }}
|
207
207
|
end
|
208
208
|
|
209
209
|
it 'applies the selector to the map/reduce' do
|
@@ -213,7 +213,7 @@ describe Mongo::Collection::View::MapReduce do
|
|
213
213
|
end
|
214
214
|
|
215
215
|
it 'includes the selector in the operation spec' do
|
216
|
-
expect(map_reduce.send(:map_reduce_spec)[:selector][:query]).to eq(
|
216
|
+
expect(map_reduce.send(:map_reduce_spec)[:selector][:query]).to eq(selector[:$query])
|
217
217
|
end
|
218
218
|
end
|
219
219
|
end
|
@@ -273,7 +273,7 @@ describe Mongo::Collection::View::MapReduce do
|
|
273
273
|
describe '#out' do
|
274
274
|
|
275
275
|
let(:location) do
|
276
|
-
{ replace
|
276
|
+
{ 'replace' => 'testing' }
|
277
277
|
end
|
278
278
|
|
279
279
|
let(:new_map_reduce) do
|
@@ -285,20 +285,20 @@ describe Mongo::Collection::View::MapReduce do
|
|
285
285
|
end
|
286
286
|
|
287
287
|
it 'includes the out value in the operation spec' do
|
288
|
-
expect(new_map_reduce.send(:map_reduce_spec)[:selector][:out]).to
|
288
|
+
expect(new_map_reduce.send(:map_reduce_spec)[:selector][:out]).to eq(location)
|
289
289
|
end
|
290
290
|
|
291
291
|
context 'when out is not defined' do
|
292
292
|
|
293
293
|
it 'defaults to inline' do
|
294
|
-
expect(map_reduce.send(:map_reduce_spec)[:selector][:out]).to eq(inline
|
294
|
+
expect(map_reduce.send(:map_reduce_spec)[:selector][:out]).to eq('inline' => 1)
|
295
295
|
end
|
296
296
|
end
|
297
297
|
|
298
298
|
context 'when out is specified in the options' do
|
299
299
|
|
300
300
|
let(:location) do
|
301
|
-
{ replace
|
301
|
+
{ 'replace' => 'testing' }
|
302
302
|
end
|
303
303
|
|
304
304
|
let(:options) do
|
@@ -310,14 +310,14 @@ describe Mongo::Collection::View::MapReduce do
|
|
310
310
|
end
|
311
311
|
|
312
312
|
it 'includes the out value in the operation spec' do
|
313
|
-
expect(map_reduce.send(:map_reduce_spec)[:selector][:out]).to
|
313
|
+
expect(map_reduce.send(:map_reduce_spec)[:selector][:out]).to eq(location)
|
314
314
|
end
|
315
315
|
end
|
316
316
|
|
317
317
|
context 'when out is not inline' do
|
318
318
|
|
319
319
|
let(:location) do
|
320
|
-
{ replace
|
320
|
+
{ 'replace' => 'testing' }
|
321
321
|
end
|
322
322
|
|
323
323
|
let(:options) do
|
@@ -325,7 +325,7 @@ describe Mongo::Collection::View::MapReduce do
|
|
325
325
|
end
|
326
326
|
|
327
327
|
it 'does not allow the operation on a secondary' do
|
328
|
-
expect(map_reduce.send(:secondary_ok?)).to be
|
328
|
+
expect(map_reduce.send(:secondary_ok?)).to be false
|
329
329
|
end
|
330
330
|
|
331
331
|
context 'when the context is not a valid server for writing' do
|
@@ -350,7 +350,7 @@ describe Mongo::Collection::View::MapReduce do
|
|
350
350
|
describe '#scope' do
|
351
351
|
|
352
352
|
let(:object) do
|
353
|
-
{ value
|
353
|
+
{ 'value' => 'testing' }
|
354
354
|
end
|
355
355
|
|
356
356
|
let(:new_map_reduce) do
|
@@ -362,7 +362,7 @@ describe Mongo::Collection::View::MapReduce do
|
|
362
362
|
end
|
363
363
|
|
364
364
|
it 'includes the scope object in the operation spec' do
|
365
|
-
expect(new_map_reduce.send(:map_reduce_spec)[:selector][:scope]).to
|
365
|
+
expect(new_map_reduce.send(:map_reduce_spec)[:selector][:scope]).to eq(object)
|
366
366
|
end
|
367
367
|
end
|
368
368
|
|
@@ -18,6 +18,40 @@ describe Mongo::Collection::View::Readable do
|
|
18
18
|
authorized_collection.delete_many
|
19
19
|
end
|
20
20
|
|
21
|
+
shared_examples_for 'a read concern aware operation' do
|
22
|
+
|
23
|
+
context 'when a read concern is provided', if: find_command_enabled? do
|
24
|
+
|
25
|
+
let(:new_view) do
|
26
|
+
Mongo::Collection::View.new(new_collection, selector, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'when the read concern is valid' do
|
30
|
+
|
31
|
+
let(:new_collection) do
|
32
|
+
authorized_collection.with(read_concern: { level: 'local' })
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'sends the read concern' do
|
36
|
+
expect { result }.to_not raise_error
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when the read concern is not valid' do
|
41
|
+
|
42
|
+
let(:new_collection) do
|
43
|
+
authorized_collection.with(read_concern: { level: 'na' })
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'raises an exception' do
|
47
|
+
expect {
|
48
|
+
result
|
49
|
+
}.to raise_error(Mongo::Error::OperationFailure)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
21
55
|
describe '#allow_partial_results' do
|
22
56
|
|
23
57
|
let(:new_view) do
|
@@ -25,7 +59,7 @@ describe Mongo::Collection::View::Readable do
|
|
25
59
|
end
|
26
60
|
|
27
61
|
it 'sets the flag' do
|
28
|
-
expect(new_view.
|
62
|
+
expect(new_view.options[:allow_partial_results]).to be true
|
29
63
|
end
|
30
64
|
|
31
65
|
it 'returns a new View' do
|
@@ -60,6 +94,15 @@ describe Mongo::Collection::View::Readable do
|
|
60
94
|
view.aggregate(pipeline)
|
61
95
|
end
|
62
96
|
|
97
|
+
context 'when incorporating read concern' do
|
98
|
+
|
99
|
+
let(:result) do
|
100
|
+
new_view.aggregate(pipeline, options).to_a
|
101
|
+
end
|
102
|
+
|
103
|
+
it_behaves_like 'a read concern aware operation'
|
104
|
+
end
|
105
|
+
|
63
106
|
context 'when not iterating the aggregation' do
|
64
107
|
|
65
108
|
it 'returns the aggregation object' do
|
@@ -127,6 +170,15 @@ describe Mongo::Collection::View::Readable do
|
|
127
170
|
view.map_reduce(map, reduce)
|
128
171
|
end
|
129
172
|
|
173
|
+
context 'when incorporating read concern' do
|
174
|
+
|
175
|
+
let(:result) do
|
176
|
+
new_view.map_reduce(map, reduce, options).to_a
|
177
|
+
end
|
178
|
+
|
179
|
+
it_behaves_like 'a read concern aware operation'
|
180
|
+
end
|
181
|
+
|
130
182
|
context 'when not iterating the map/reduce' do
|
131
183
|
|
132
184
|
it 'returns the map/reduce object' do
|
@@ -218,6 +270,19 @@ describe Mongo::Collection::View::Readable do
|
|
218
270
|
authorized_collection.delete_many
|
219
271
|
end
|
220
272
|
|
273
|
+
let(:result) do
|
274
|
+
view.count(options)
|
275
|
+
end
|
276
|
+
|
277
|
+
context 'when incorporating read concern' do
|
278
|
+
|
279
|
+
let(:result) do
|
280
|
+
new_view.count(options)
|
281
|
+
end
|
282
|
+
|
283
|
+
it_behaves_like 'a read concern aware operation'
|
284
|
+
end
|
285
|
+
|
221
286
|
context 'when a selector is provided' do
|
222
287
|
|
223
288
|
let(:selector) do
|
@@ -257,6 +322,15 @@ describe Mongo::Collection::View::Readable do
|
|
257
322
|
|
258
323
|
describe '#distinct' do
|
259
324
|
|
325
|
+
context 'when incorporating read concern' do
|
326
|
+
|
327
|
+
let(:result) do
|
328
|
+
new_view.distinct(:field, options)
|
329
|
+
end
|
330
|
+
|
331
|
+
it_behaves_like 'a read concern aware operation'
|
332
|
+
end
|
333
|
+
|
260
334
|
context 'when a selector is provided' do
|
261
335
|
|
262
336
|
let(:selector) do
|
@@ -498,7 +572,7 @@ describe Mongo::Collection::View::Readable do
|
|
498
572
|
end
|
499
573
|
|
500
574
|
it 'sets the flag' do
|
501
|
-
expect(new_view.
|
575
|
+
expect(new_view.options[:no_cursor_timeout]).to be true
|
502
576
|
end
|
503
577
|
|
504
578
|
it 'returns a new View' do
|
@@ -518,6 +592,10 @@ describe Mongo::Collection::View::Readable do
|
|
518
592
|
{ 'y' => 1 }
|
519
593
|
end
|
520
594
|
|
595
|
+
before do
|
596
|
+
authorized_collection.insert_one(y: 'value', a: 'other_value')
|
597
|
+
end
|
598
|
+
|
521
599
|
it 'sets the projection' do
|
522
600
|
new_view = view.projection(new_projection)
|
523
601
|
expect(new_view.projection).to eq(new_projection)
|
@@ -526,6 +604,10 @@ describe Mongo::Collection::View::Readable do
|
|
526
604
|
it 'returns a new View' do
|
527
605
|
expect(view.projection(new_projection)).not_to be(view)
|
528
606
|
end
|
607
|
+
|
608
|
+
it 'returns only that field on the collection' do
|
609
|
+
expect(view.projection(new_projection).first.keys).to match_array(['_id', 'y'])
|
610
|
+
end
|
529
611
|
end
|
530
612
|
|
531
613
|
context 'when projection is not specified' do
|
@@ -636,13 +718,13 @@ describe Mongo::Collection::View::Readable do
|
|
636
718
|
describe '#modifiers' do
|
637
719
|
|
638
720
|
let(:options) do
|
639
|
-
{ :modifiers => {
|
721
|
+
{ :modifiers => { '$orderby' => 1 } }
|
640
722
|
end
|
641
723
|
|
642
724
|
context 'when a modifiers document is specified' do
|
643
725
|
|
644
726
|
let(:new_modifiers) do
|
645
|
-
{
|
727
|
+
{ '$orderby' => -1 }
|
646
728
|
end
|
647
729
|
|
648
730
|
it 'sets the new_modifiers document' do
|
@@ -770,81 +852,5 @@ describe Mongo::Collection::View::Readable do
|
|
770
852
|
expect(view.sort).to eq(options[:sort])
|
771
853
|
end
|
772
854
|
end
|
773
|
-
|
774
|
-
context 'when an option is a cursor flag' do
|
775
|
-
|
776
|
-
let(:query_spec_options) do
|
777
|
-
view.send(:query_spec)[:options]
|
778
|
-
end
|
779
|
-
|
780
|
-
context 'when allow_partial_results is set as an option' do
|
781
|
-
|
782
|
-
let(:options) do
|
783
|
-
{ :allow_partial_results => true }
|
784
|
-
end
|
785
|
-
|
786
|
-
it 'sets the cursor flag' do
|
787
|
-
expect(query_spec_options[:flags]).to eq([:partial])
|
788
|
-
end
|
789
|
-
|
790
|
-
context 'when allow_partial_results is also called as a method' do
|
791
|
-
|
792
|
-
before do
|
793
|
-
view.allow_partial_results
|
794
|
-
end
|
795
|
-
|
796
|
-
it 'sets only one cursor flag' do
|
797
|
-
expect(query_spec_options[:flags]).to eq([:partial])
|
798
|
-
end
|
799
|
-
end
|
800
|
-
end
|
801
|
-
|
802
|
-
context 'when oplog_replay is set as an option' do
|
803
|
-
|
804
|
-
let(:options) do
|
805
|
-
{ :oplog_replay => true }
|
806
|
-
end
|
807
|
-
|
808
|
-
it 'sets the cursor flag' do
|
809
|
-
expect(query_spec_options[:flags]).to eq([:oplog_replay])
|
810
|
-
end
|
811
|
-
end
|
812
|
-
|
813
|
-
context 'when no_cursor_timeout is set as an option' do
|
814
|
-
|
815
|
-
let(:options) do
|
816
|
-
{ :no_cursor_timeout => true }
|
817
|
-
end
|
818
|
-
|
819
|
-
it 'sets the cursor flag' do
|
820
|
-
expect(query_spec_options[:flags]).to eq([:no_cursor_timeout])
|
821
|
-
end
|
822
|
-
end
|
823
|
-
|
824
|
-
context 'when cursor_type is set as an option' do
|
825
|
-
|
826
|
-
context 'when :tailable is the cursor type' do
|
827
|
-
|
828
|
-
let(:options) do
|
829
|
-
{ :cursor_type => :tailable }
|
830
|
-
end
|
831
|
-
|
832
|
-
it 'sets the cursor flag' do
|
833
|
-
expect(query_spec_options[:flags]).to eq([:tailable_cursor])
|
834
|
-
end
|
835
|
-
end
|
836
|
-
|
837
|
-
context 'when :tailable_await is the cursor type' do
|
838
|
-
|
839
|
-
let(:options) do
|
840
|
-
{ :cursor_type => :tailable_await }
|
841
|
-
end
|
842
|
-
|
843
|
-
it 'sets the cursor flags' do
|
844
|
-
expect(query_spec_options[:flags]).to eq([:await_data, :tailable_cursor])
|
845
|
-
end
|
846
|
-
end
|
847
|
-
end
|
848
|
-
end
|
849
855
|
end
|
850
856
|
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mongo::Collection::View do
|
4
4
|
|
5
|
-
let(:
|
5
|
+
let(:filter) do
|
6
6
|
{}
|
7
7
|
end
|
8
8
|
|
@@ -11,187 +11,13 @@ describe Mongo::Collection::View do
|
|
11
11
|
end
|
12
12
|
|
13
13
|
let(:view) do
|
14
|
-
described_class.new(authorized_collection,
|
14
|
+
described_class.new(authorized_collection, filter, options)
|
15
15
|
end
|
16
16
|
|
17
17
|
after do
|
18
18
|
authorized_collection.delete_many
|
19
19
|
end
|
20
20
|
|
21
|
-
context 'when query modifiers are provided' do
|
22
|
-
|
23
|
-
context 'when a selector has a query modifier' do
|
24
|
-
|
25
|
-
let(:options) do
|
26
|
-
{}
|
27
|
-
end
|
28
|
-
|
29
|
-
let(:expected_modifiers) do
|
30
|
-
BSON::Document.new(selector)
|
31
|
-
end
|
32
|
-
|
33
|
-
let(:parsed_selector) do
|
34
|
-
{}
|
35
|
-
end
|
36
|
-
|
37
|
-
let(:query_selector) do
|
38
|
-
BSON::Document.new(selector)
|
39
|
-
end
|
40
|
-
|
41
|
-
context 'when the $query key is a string' do
|
42
|
-
|
43
|
-
let(:selector) do
|
44
|
-
{ "$query" => { a: 1 }, :$someMod => 100 }
|
45
|
-
end
|
46
|
-
|
47
|
-
let(:expected_modifiers) do
|
48
|
-
BSON::Document.new(selector)
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'sets the modifiers' do
|
52
|
-
expect(view.instance_variable_get(:@modifiers)).to eq(expected_modifiers)
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'removes the modifiers from the selector' do
|
56
|
-
expect(view.selector).to eq(parsed_selector)
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'creates the correct query selector' do
|
60
|
-
expect(view.send(:query_spec)[:selector]).to eq(query_selector)
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'when the $query key is a symbol' do
|
66
|
-
|
67
|
-
let(:selector) do
|
68
|
-
{ :$query => { a: 1 }, :$someMod => 100 }
|
69
|
-
end
|
70
|
-
|
71
|
-
let(:expected_modifiers) do
|
72
|
-
BSON::Document.new(selector)
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'sets the modifiers' do
|
76
|
-
expect(view.instance_variable_get(:@modifiers)).to eq(expected_modifiers)
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'removes the modifiers from the selector' do
|
80
|
-
expect(view.selector).to eq(parsed_selector)
|
81
|
-
end
|
82
|
-
|
83
|
-
it 'creates the correct query selector' do
|
84
|
-
expect(view.send(:query_spec)[:selector]).to eq(query_selector)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context 'when a modifiers document is provided in the options' do
|
90
|
-
|
91
|
-
let(:selector) do
|
92
|
-
{ a: 1 }
|
93
|
-
end
|
94
|
-
|
95
|
-
let(:options) do
|
96
|
-
{ :modifiers => { :$someMod => 100 } }
|
97
|
-
end
|
98
|
-
|
99
|
-
let(:expected_modifiers) do
|
100
|
-
options[:modifiers]
|
101
|
-
end
|
102
|
-
|
103
|
-
let(:parsed_selector) do
|
104
|
-
{ a: 1 }
|
105
|
-
end
|
106
|
-
|
107
|
-
let(:query_selector) do
|
108
|
-
BSON::Document.new(:$query => { a: 1 }, :$someMod => 100)
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'sets the modifiers' do
|
112
|
-
expect(view.instance_variable_get(:@modifiers)).to eq(expected_modifiers)
|
113
|
-
end
|
114
|
-
|
115
|
-
it 'removes the modifiers from the selector' do
|
116
|
-
expect(view.selector).to eq(parsed_selector)
|
117
|
-
end
|
118
|
-
|
119
|
-
it 'creates the correct query selector' do
|
120
|
-
expect(view.send(:query_spec)[:selector]).to eq(query_selector)
|
121
|
-
end
|
122
|
-
|
123
|
-
context 'when modifiers and options are both provided' do
|
124
|
-
|
125
|
-
let(:selector) do
|
126
|
-
{ a: 1 }
|
127
|
-
end
|
128
|
-
|
129
|
-
let(:options) do
|
130
|
-
{ :sort => { a: Mongo::Index::ASCENDING }, :modifiers => { :$orderby => { a: Mongo::Index::DESCENDING } } }
|
131
|
-
end
|
132
|
-
|
133
|
-
let(:expected_modifiers) do
|
134
|
-
{ :$orderby => options[:sort] }
|
135
|
-
end
|
136
|
-
|
137
|
-
let(:parsed_selector) do
|
138
|
-
{ a: 1 }
|
139
|
-
end
|
140
|
-
|
141
|
-
let(:query_selector) do
|
142
|
-
BSON::Document.new(:$query => selector, :$orderby => { a: Mongo::Index::ASCENDING })
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'sets the modifiers' do
|
146
|
-
expect(view.instance_variable_get(:@modifiers)).to eq(expected_modifiers)
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'removes the modifiers from the selector' do
|
150
|
-
expect(view.selector).to eq(parsed_selector)
|
151
|
-
end
|
152
|
-
|
153
|
-
it 'creates the correct query selector' do
|
154
|
-
expect(view.send(:query_spec)[:selector]).to eq(query_selector)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
context 'when modifiers, options and a query modifier are provided' do
|
159
|
-
|
160
|
-
let(:selector) do
|
161
|
-
{ b: 2, :$query => { a: 1 }, :$someMod => 100 }
|
162
|
-
end
|
163
|
-
|
164
|
-
let(:options) do
|
165
|
-
{ :sort => { a: Mongo::Index::ASCENDING }, :modifiers => { :$someMod => true, :$orderby => { a: Mongo::Index::DESCENDING } } }
|
166
|
-
end
|
167
|
-
|
168
|
-
let(:expected_modifiers) do
|
169
|
-
{ :$query => { a: 1 }, :$orderby => { a: Mongo::Index::ASCENDING }, :$someMod => 100 }
|
170
|
-
end
|
171
|
-
|
172
|
-
let(:parsed_selector) do
|
173
|
-
{ b: 2 }
|
174
|
-
end
|
175
|
-
|
176
|
-
let(:query_selector) do
|
177
|
-
BSON::Document.new(:$query => { a: 1 }, :$someMod => 100, :$orderby => { a: Mongo::Index::ASCENDING })
|
178
|
-
end
|
179
|
-
|
180
|
-
it 'sets the modifiers' do
|
181
|
-
expect(view.instance_variable_get(:@modifiers)).to eq(expected_modifiers)
|
182
|
-
end
|
183
|
-
|
184
|
-
it 'removes the modifiers from the selector' do
|
185
|
-
expect(view.selector).to eq(parsed_selector)
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'creates the correct query selector' do
|
189
|
-
expect(view.send(:query_spec)[:selector]).to eq(query_selector)
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
21
|
describe '#==' do
|
196
22
|
|
197
23
|
context 'when the other object is not a collection view' do
|
@@ -203,10 +29,10 @@ describe Mongo::Collection::View do
|
|
203
29
|
end
|
204
30
|
end
|
205
31
|
|
206
|
-
context 'when the views have the same collection,
|
32
|
+
context 'when the views have the same collection, filter, and options' do
|
207
33
|
|
208
34
|
let(:other) do
|
209
|
-
described_class.new(authorized_collection,
|
35
|
+
described_class.new(authorized_collection, filter, options)
|
210
36
|
end
|
211
37
|
|
212
38
|
it 'returns true' do
|
@@ -221,7 +47,7 @@ describe Mongo::Collection::View do
|
|
221
47
|
end
|
222
48
|
|
223
49
|
let(:other) do
|
224
|
-
described_class.new(other_collection,
|
50
|
+
described_class.new(other_collection, filter, options)
|
225
51
|
end
|
226
52
|
|
227
53
|
it 'returns false' do
|
@@ -229,14 +55,14 @@ describe Mongo::Collection::View do
|
|
229
55
|
end
|
230
56
|
end
|
231
57
|
|
232
|
-
context 'when two views have a different
|
58
|
+
context 'when two views have a different filter' do
|
233
59
|
|
234
|
-
let(:
|
60
|
+
let(:other_filter) do
|
235
61
|
{ 'name' => 'Emily' }
|
236
62
|
end
|
237
63
|
|
238
64
|
let(:other) do
|
239
|
-
described_class.new(authorized_collection,
|
65
|
+
described_class.new(authorized_collection, other_filter, options)
|
240
66
|
end
|
241
67
|
|
242
68
|
it 'returns false' do
|
@@ -251,7 +77,7 @@ describe Mongo::Collection::View do
|
|
251
77
|
end
|
252
78
|
|
253
79
|
let(:other) do
|
254
|
-
described_class.new(authorized_collection,
|
80
|
+
described_class.new(authorized_collection, filter, other_options)
|
255
81
|
end
|
256
82
|
|
257
83
|
it 'returns false' do
|
@@ -270,8 +96,8 @@ describe Mongo::Collection::View do
|
|
270
96
|
expect(view.options).not_to be(view_clone.options)
|
271
97
|
end
|
272
98
|
|
273
|
-
it 'dups the
|
274
|
-
expect(view.
|
99
|
+
it 'dups the filter' do
|
100
|
+
expect(view.filter).not_to be(view_clone.filter)
|
275
101
|
end
|
276
102
|
|
277
103
|
it 'references the same collection' do
|
@@ -293,487 +119,6 @@ describe Mongo::Collection::View do
|
|
293
119
|
authorized_collection.delete_many
|
294
120
|
end
|
295
121
|
|
296
|
-
context 'when sending the initial query' do
|
297
|
-
|
298
|
-
let(:returned) do
|
299
|
-
view.to_a
|
300
|
-
end
|
301
|
-
|
302
|
-
let(:query_spec) do
|
303
|
-
view.send(:query_spec)
|
304
|
-
end
|
305
|
-
|
306
|
-
context 'when limit is specified' do
|
307
|
-
|
308
|
-
let(:options) do
|
309
|
-
{ :limit => 5 }
|
310
|
-
end
|
311
|
-
|
312
|
-
let(:returned) do
|
313
|
-
view.to_a
|
314
|
-
end
|
315
|
-
|
316
|
-
it 'sets the limit on the initial query' do
|
317
|
-
expect(query_spec[:options][:limit]).to eq(options[:limit])
|
318
|
-
end
|
319
|
-
|
320
|
-
it 'returns limited documents' do
|
321
|
-
expect(returned.count).to eq(5)
|
322
|
-
end
|
323
|
-
|
324
|
-
it 'iterates over all of the documents' do
|
325
|
-
returned.each do |doc|
|
326
|
-
expect(doc).to have_key('field')
|
327
|
-
end
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|
331
|
-
context 'when batch size is specified' do
|
332
|
-
|
333
|
-
let(:options) do
|
334
|
-
{ :batch_size => 5 }
|
335
|
-
end
|
336
|
-
|
337
|
-
let(:returned) do
|
338
|
-
view.to_a
|
339
|
-
end
|
340
|
-
|
341
|
-
it 'sets the batch size on the initial query' do
|
342
|
-
expect(query_spec[:options][:batch_size]).to eq(options[:batch_size])
|
343
|
-
end
|
344
|
-
|
345
|
-
it 'returns all the documents' do
|
346
|
-
expect(returned.count).to eq(10)
|
347
|
-
end
|
348
|
-
|
349
|
-
it 'iterates over all of the documents' do
|
350
|
-
returned.each do |doc|
|
351
|
-
expect(doc).to have_key('field')
|
352
|
-
end
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
context 'when no limit is specified' do
|
357
|
-
|
358
|
-
it 'does not set a limit on the initial query' do
|
359
|
-
expect(query_spec[:options][:limit]).to be_nil
|
360
|
-
end
|
361
|
-
|
362
|
-
it 'returns all the documents' do
|
363
|
-
expect(returned.count).to eq(10)
|
364
|
-
end
|
365
|
-
|
366
|
-
it 'iterates over all of the documents' do
|
367
|
-
returned.each do |doc|
|
368
|
-
expect(doc).to have_key('field')
|
369
|
-
end
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
|
-
context 'when batch size is greater than limit' do
|
374
|
-
|
375
|
-
let(:options) do
|
376
|
-
{ :batch_size => 5, :limit => 3 }
|
377
|
-
end
|
378
|
-
|
379
|
-
let(:returned) do
|
380
|
-
view.to_a
|
381
|
-
end
|
382
|
-
|
383
|
-
it 'sets the limit on the initial query' do
|
384
|
-
expect(query_spec[:options][:limit]).to eq(options[:limit])
|
385
|
-
end
|
386
|
-
|
387
|
-
it 'returns the limit of documents' do
|
388
|
-
expect(returned.count).to eq(3)
|
389
|
-
end
|
390
|
-
|
391
|
-
it 'iterates over all of the documents' do
|
392
|
-
returned.each do |doc|
|
393
|
-
expect(doc).to have_key('field')
|
394
|
-
end
|
395
|
-
end
|
396
|
-
end
|
397
|
-
|
398
|
-
context 'when limit is greater than batch size' do
|
399
|
-
|
400
|
-
let(:options) do
|
401
|
-
{ :limit => 5, :batch_size => 3 }
|
402
|
-
end
|
403
|
-
|
404
|
-
let(:returned) do
|
405
|
-
view.to_a
|
406
|
-
end
|
407
|
-
|
408
|
-
it 'sets the batch size on the initial query' do
|
409
|
-
expect(query_spec[:options][:batch_size]).to eq(options[:batch_size])
|
410
|
-
end
|
411
|
-
|
412
|
-
it 'sets the limit on the initial query' do
|
413
|
-
expect(query_spec[:options][:limit]).to eq(options[:limit])
|
414
|
-
end
|
415
|
-
|
416
|
-
it 'returns the limit of documents' do
|
417
|
-
expect(returned.count).to eq(5)
|
418
|
-
end
|
419
|
-
|
420
|
-
it 'iterates over all of the documents' do
|
421
|
-
returned.each do |doc|
|
422
|
-
expect(doc).to have_key('field')
|
423
|
-
end
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
context 'when the selector has special fields' do
|
428
|
-
|
429
|
-
context 'when a snapshot option is specified' do
|
430
|
-
|
431
|
-
let(:options) do
|
432
|
-
{ :snapshot => true }
|
433
|
-
end
|
434
|
-
|
435
|
-
before do
|
436
|
-
expect(view).to receive(:special_selector).and_call_original
|
437
|
-
end
|
438
|
-
|
439
|
-
it 'creates a special query selector' do
|
440
|
-
expect(query_spec[:selector][:$snapshot]).to eq(options[:snapshot])
|
441
|
-
end
|
442
|
-
|
443
|
-
it 'iterates over all of the documents' do
|
444
|
-
returned.each do |doc|
|
445
|
-
expect(doc).to have_key('field')
|
446
|
-
end
|
447
|
-
end
|
448
|
-
end
|
449
|
-
|
450
|
-
context 'when a max_scan option is provided' do
|
451
|
-
|
452
|
-
let(:options) do
|
453
|
-
{ :max_scan => 100 }
|
454
|
-
end
|
455
|
-
|
456
|
-
before do
|
457
|
-
expect(view).to receive(:special_selector).and_call_original
|
458
|
-
end
|
459
|
-
|
460
|
-
it 'creates a special query selector' do
|
461
|
-
expect(query_spec[:selector][:$maxScan]).to eq(options[:max_scan])
|
462
|
-
end
|
463
|
-
|
464
|
-
it 'iterates over all of the documents' do
|
465
|
-
returned.each do |doc|
|
466
|
-
expect(doc).to have_key('field')
|
467
|
-
end
|
468
|
-
end
|
469
|
-
end
|
470
|
-
|
471
|
-
context 'when a max_time_ms option is provided' do
|
472
|
-
|
473
|
-
let(:options) do
|
474
|
-
{ :max_time_ms => 100 }
|
475
|
-
end
|
476
|
-
|
477
|
-
before do
|
478
|
-
expect(view).to receive(:special_selector).and_call_original
|
479
|
-
end
|
480
|
-
|
481
|
-
it 'creates a special query selector' do
|
482
|
-
expect(query_spec[:selector][:$maxTimeMS]).to eq(options[:max_time_ms])
|
483
|
-
end
|
484
|
-
|
485
|
-
it 'iterates over all of the documents' do
|
486
|
-
returned.each do |doc|
|
487
|
-
expect(doc).to have_key('field')
|
488
|
-
end
|
489
|
-
end
|
490
|
-
end
|
491
|
-
|
492
|
-
context 'when a show_disk_loc option is provided' do
|
493
|
-
|
494
|
-
let(:options) do
|
495
|
-
{ :show_disk_loc => true }
|
496
|
-
end
|
497
|
-
|
498
|
-
before do
|
499
|
-
expect(view).to receive(:special_selector).and_call_original
|
500
|
-
end
|
501
|
-
|
502
|
-
it 'creates a special query selector' do
|
503
|
-
expect(query_spec[:selector][:$showDiskLoc]).to eq(options[:show_disk_loc])
|
504
|
-
end
|
505
|
-
|
506
|
-
it 'iterates over all of the documents' do
|
507
|
-
returned.each do |doc|
|
508
|
-
expect(doc).to have_key('field')
|
509
|
-
end
|
510
|
-
end
|
511
|
-
end
|
512
|
-
end
|
513
|
-
|
514
|
-
context 'when sorting' do
|
515
|
-
|
516
|
-
let(:options) do
|
517
|
-
{ :sort => {'x' => Mongo::Index::ASCENDING }}
|
518
|
-
end
|
519
|
-
|
520
|
-
before do
|
521
|
-
expect(view).to receive(:special_selector).and_call_original
|
522
|
-
end
|
523
|
-
|
524
|
-
it 'creates a special query selector' do
|
525
|
-
expect(query_spec[:selector][:$orderby]).to eq(options[:sort])
|
526
|
-
end
|
527
|
-
|
528
|
-
it 'iterates over all of the documents' do
|
529
|
-
returned.each do |doc|
|
530
|
-
expect(doc).to have_key('field')
|
531
|
-
end
|
532
|
-
end
|
533
|
-
end
|
534
|
-
|
535
|
-
context 'when providing a hint' do
|
536
|
-
|
537
|
-
context 'when the hint is bad' do
|
538
|
-
|
539
|
-
let(:options) do
|
540
|
-
{ :hint => { 'x' => Mongo::Index::ASCENDING }}
|
541
|
-
end
|
542
|
-
|
543
|
-
before do
|
544
|
-
expect(view).to receive(:special_selector).and_call_original
|
545
|
-
end
|
546
|
-
|
547
|
-
it 'creates a special query selector' do
|
548
|
-
expect(query_spec[:selector][:$hint]).to eq(options[:hint])
|
549
|
-
end
|
550
|
-
end
|
551
|
-
end
|
552
|
-
|
553
|
-
context 'when providing a comment' do
|
554
|
-
|
555
|
-
let(:options) do
|
556
|
-
{ :comment => 'query1' }
|
557
|
-
end
|
558
|
-
|
559
|
-
before do
|
560
|
-
expect(view).to receive(:special_selector).and_call_original
|
561
|
-
end
|
562
|
-
|
563
|
-
it 'creates a special query selector' do
|
564
|
-
expect(query_spec[:selector][:$comment]).to eq(options[:comment])
|
565
|
-
end
|
566
|
-
|
567
|
-
it 'iterates over all of the documents' do
|
568
|
-
returned.each do |doc|
|
569
|
-
expect(doc).to have_key('field')
|
570
|
-
end
|
571
|
-
end
|
572
|
-
end
|
573
|
-
|
574
|
-
context 'when the cluster is sharded', if: sharded? do
|
575
|
-
|
576
|
-
before do
|
577
|
-
expect(view).to receive(:special_selector).and_call_original
|
578
|
-
end
|
579
|
-
|
580
|
-
it 'iterates over all of the documents' do
|
581
|
-
view.each do |doc|
|
582
|
-
expect(doc).to have_key('field')
|
583
|
-
end
|
584
|
-
end
|
585
|
-
|
586
|
-
context 'when there is a read preference' do
|
587
|
-
|
588
|
-
let(:collection) do
|
589
|
-
authorized_collection.with(read: { mode: :secondary})
|
590
|
-
end
|
591
|
-
|
592
|
-
let(:view) do
|
593
|
-
described_class.new(collection, selector, options)
|
594
|
-
end
|
595
|
-
|
596
|
-
let(:formatted_read_pref) do
|
597
|
-
BSON::Document.new(Mongo::ServerSelector.get(mode: :secondary).to_mongos)
|
598
|
-
end
|
599
|
-
|
600
|
-
it 'adds the formatted read preference to the selector' do
|
601
|
-
expect(view.send(:query_spec)[:selector][:$readPreference]).to eq(formatted_read_pref)
|
602
|
-
end
|
603
|
-
end
|
604
|
-
|
605
|
-
context 'when the read preference is primary' do
|
606
|
-
|
607
|
-
let(:collection) do
|
608
|
-
authorized_collection.with(read: { mode: :primary})
|
609
|
-
end
|
610
|
-
|
611
|
-
let(:view) do
|
612
|
-
described_class.new(collection, selector, options)
|
613
|
-
end
|
614
|
-
|
615
|
-
it 'does not add the formatted read preference to the selector' do
|
616
|
-
expect(view.send(:query_spec)[:selector][:$readPreference]).to be(nil)
|
617
|
-
end
|
618
|
-
end
|
619
|
-
end
|
620
|
-
|
621
|
-
context 'when a modifier document is provided' do
|
622
|
-
|
623
|
-
let(:options) do
|
624
|
-
{ :modifiers => {
|
625
|
-
:$orderby => {'x' => Mongo::Index::ASCENDING }
|
626
|
-
}
|
627
|
-
}
|
628
|
-
end
|
629
|
-
|
630
|
-
before do
|
631
|
-
expect(view).to receive(:special_selector).and_call_original
|
632
|
-
end
|
633
|
-
|
634
|
-
it 'creates a special query selector' do
|
635
|
-
expect(query_spec[:selector][:$orderby]).to eq(options[:modifiers][:$orderby])
|
636
|
-
end
|
637
|
-
|
638
|
-
it 'iterates over all of the documents' do
|
639
|
-
view.each do |doc|
|
640
|
-
expect(doc).to have_key('field')
|
641
|
-
end
|
642
|
-
end
|
643
|
-
|
644
|
-
context 'when $explain is specified' do
|
645
|
-
let(:options) do
|
646
|
-
{ :modifiers => {
|
647
|
-
:$explain => 1
|
648
|
-
}
|
649
|
-
}
|
650
|
-
end
|
651
|
-
|
652
|
-
let(:explain) do
|
653
|
-
view.to_a.first
|
654
|
-
end
|
655
|
-
|
656
|
-
it 'executes an explain' do
|
657
|
-
expect(explain['cursor'] == 'BasicCursor' ||
|
658
|
-
explain['queryPlanner']).to be_truthy
|
659
|
-
end
|
660
|
-
|
661
|
-
end
|
662
|
-
|
663
|
-
context 'when an option is also provided' do
|
664
|
-
|
665
|
-
context 'when $orderby and sort are specified' do
|
666
|
-
|
667
|
-
let(:options) do
|
668
|
-
{ :modifiers => {
|
669
|
-
:$orderby => { 'x' => Mongo::Index::ASCENDING }
|
670
|
-
},
|
671
|
-
:sort => { 'x' => Mongo::Index::DESCENDING }
|
672
|
-
}
|
673
|
-
end
|
674
|
-
|
675
|
-
it 'overrides the modifier value with the option value' do
|
676
|
-
expect(query_spec[:selector][:$orderby]).to eq(options[:sort])
|
677
|
-
end
|
678
|
-
end
|
679
|
-
|
680
|
-
context 'when $comment and comment are specified' do
|
681
|
-
|
682
|
-
let(:options) do
|
683
|
-
{ :modifiers => {
|
684
|
-
:$comment => 'query1'
|
685
|
-
},
|
686
|
-
:comment => 'query2'
|
687
|
-
}
|
688
|
-
end
|
689
|
-
|
690
|
-
it 'overrides the modifier value with the option value' do
|
691
|
-
expect(query_spec[:selector][:$comment]).to eq(options[:comment])
|
692
|
-
end
|
693
|
-
end
|
694
|
-
|
695
|
-
context 'when $hint and hint are specified' do
|
696
|
-
|
697
|
-
let(:options) do
|
698
|
-
{ :modifiers => {
|
699
|
-
:$hint => 'x'
|
700
|
-
},
|
701
|
-
:hint => 'y'
|
702
|
-
}
|
703
|
-
end
|
704
|
-
|
705
|
-
it 'overrides the modifier value with the option value' do
|
706
|
-
expect(query_spec[:selector][:$hint]).to eq(options[:hint])
|
707
|
-
end
|
708
|
-
|
709
|
-
end
|
710
|
-
|
711
|
-
context 'when $maxScan and max_scan are specified' do
|
712
|
-
|
713
|
-
let(:options) do
|
714
|
-
{ :modifiers => {
|
715
|
-
:$maxScan => 4
|
716
|
-
},
|
717
|
-
:max_scan => 5
|
718
|
-
}
|
719
|
-
end
|
720
|
-
|
721
|
-
it 'overrides the modifier value with the option value' do
|
722
|
-
expect(query_spec[:selector][:$maxScan]).to eq(options[:max_scan])
|
723
|
-
end
|
724
|
-
end
|
725
|
-
|
726
|
-
context 'when $maxTimeMS and max_time_ms are specified' do
|
727
|
-
|
728
|
-
let(:options) do
|
729
|
-
{ :modifiers => {
|
730
|
-
:$maxTimeMS => 100
|
731
|
-
},
|
732
|
-
:max_time_ms => 200
|
733
|
-
}
|
734
|
-
end
|
735
|
-
|
736
|
-
it 'overrides the modifier value with the option value' do
|
737
|
-
expect(query_spec[:selector][:$maxTimeMS]).to eq(options[:max_time_ms])
|
738
|
-
end
|
739
|
-
end
|
740
|
-
|
741
|
-
context 'when $query and a selector are specified' do
|
742
|
-
|
743
|
-
let(:selector) do
|
744
|
-
{ 'y' => 1 }
|
745
|
-
end
|
746
|
-
|
747
|
-
let(:options) do
|
748
|
-
{ :modifiers => {
|
749
|
-
:$query => { 'field' => 1 }
|
750
|
-
}
|
751
|
-
}
|
752
|
-
end
|
753
|
-
|
754
|
-
it 'overrides the modifier value with the option value' do
|
755
|
-
expect(query_spec[:selector][:$query]).to eq(options[:modifiers][:$query])
|
756
|
-
end
|
757
|
-
end
|
758
|
-
end
|
759
|
-
end
|
760
|
-
end
|
761
|
-
|
762
|
-
context 'when there are no special fields' do
|
763
|
-
|
764
|
-
before do
|
765
|
-
expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
|
766
|
-
expect(spec[:selector]).to eq(selector)
|
767
|
-
end.and_call_original
|
768
|
-
end
|
769
|
-
|
770
|
-
it 'creates a normal query spec' do
|
771
|
-
view.each do |doc|
|
772
|
-
expect(doc).to have_key('field')
|
773
|
-
end
|
774
|
-
end
|
775
|
-
end
|
776
|
-
|
777
122
|
context 'when a block is not provided' do
|
778
123
|
|
779
124
|
let(:enumerator) do
|
@@ -793,14 +138,17 @@ describe Mongo::Collection::View do
|
|
793
138
|
{ :batch_size => 1 }
|
794
139
|
end
|
795
140
|
|
141
|
+
let(:cursor) do
|
142
|
+
view.instance_variable_get(:@cursor)
|
143
|
+
end
|
144
|
+
|
796
145
|
before do
|
797
|
-
|
798
|
-
|
799
|
-
cursor = view.instance_variable_get(:@cursor)
|
800
|
-
expect(cursor).to receive(:kill_cursors).and_call_original
|
146
|
+
view.to_enum.next
|
147
|
+
cursor.instance_variable_set(:@cursor_id, 1) unless find_command_enabled?
|
801
148
|
end
|
802
149
|
|
803
150
|
it 'sends a kill cursors command for the cursor' do
|
151
|
+
expect(cursor).to receive(:kill_cursors).and_call_original
|
804
152
|
view.close_query
|
805
153
|
end
|
806
154
|
end
|
@@ -809,10 +157,10 @@ describe Mongo::Collection::View do
|
|
809
157
|
describe '#hash' do
|
810
158
|
|
811
159
|
let(:other) do
|
812
|
-
described_class.new(authorized_collection,
|
160
|
+
described_class.new(authorized_collection, filter, options)
|
813
161
|
end
|
814
162
|
|
815
|
-
it 'returns a unique value based on collection,
|
163
|
+
it 'returns a unique value based on collection, filter, options' do
|
816
164
|
expect(view.hash).to eq(other.hash)
|
817
165
|
end
|
818
166
|
|
@@ -823,7 +171,7 @@ describe Mongo::Collection::View do
|
|
823
171
|
end
|
824
172
|
|
825
173
|
let(:other) do
|
826
|
-
described_class.new(other_collection,
|
174
|
+
described_class.new(other_collection, filter, options)
|
827
175
|
end
|
828
176
|
|
829
177
|
it 'returns different hash values' do
|
@@ -831,14 +179,14 @@ describe Mongo::Collection::View do
|
|
831
179
|
end
|
832
180
|
end
|
833
181
|
|
834
|
-
context 'when two views only have different
|
182
|
+
context 'when two views only have different filter' do
|
835
183
|
|
836
|
-
let(:
|
184
|
+
let(:other_filter) do
|
837
185
|
{ 'name' => 'Emily' }
|
838
186
|
end
|
839
187
|
|
840
188
|
let(:other) do
|
841
|
-
described_class.new(authorized_collection,
|
189
|
+
described_class.new(authorized_collection, other_filter, options)
|
842
190
|
end
|
843
191
|
|
844
192
|
it 'returns different hash values' do
|
@@ -853,7 +201,7 @@ describe Mongo::Collection::View do
|
|
853
201
|
end
|
854
202
|
|
855
203
|
let(:other) do
|
856
|
-
described_class.new(authorized_collection,
|
204
|
+
described_class.new(authorized_collection, filter, other_options)
|
857
205
|
end
|
858
206
|
|
859
207
|
it 'returns different hash values' do
|
@@ -864,53 +212,111 @@ describe Mongo::Collection::View do
|
|
864
212
|
|
865
213
|
describe '#initialize' do
|
866
214
|
|
867
|
-
|
868
|
-
{ :limit => 5 }
|
869
|
-
end
|
215
|
+
context 'when the filter is not a valid document' do
|
870
216
|
|
871
|
-
|
872
|
-
|
873
|
-
|
217
|
+
let(:filter) do
|
218
|
+
'y'
|
219
|
+
end
|
874
220
|
|
875
|
-
|
876
|
-
|
221
|
+
let(:options) do
|
222
|
+
{ limit: 5 }
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'raises an error' do
|
226
|
+
expect do
|
227
|
+
view
|
228
|
+
end.to raise_error(Mongo::Error::InvalidDocument)
|
229
|
+
end
|
877
230
|
end
|
878
231
|
|
879
|
-
|
880
|
-
|
232
|
+
context 'when the filter and options are standard' do
|
233
|
+
|
234
|
+
let(:filter) do
|
235
|
+
{ 'name' => 'test' }
|
236
|
+
end
|
237
|
+
|
238
|
+
let(:options) do
|
239
|
+
{ 'sort' => { 'name' => 1 }}
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'parses a standard filter' do
|
243
|
+
expect(view.filter).to eq(filter)
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'parses standard options' do
|
247
|
+
expect(view.options).to eq(options)
|
248
|
+
end
|
881
249
|
end
|
882
250
|
|
883
|
-
|
884
|
-
|
251
|
+
context 'when the filter contains modifiers' do
|
252
|
+
|
253
|
+
let(:filter) do
|
254
|
+
{ :$query => { :name => 'test' }, :$comment => 'testing' }
|
255
|
+
end
|
256
|
+
|
257
|
+
let(:options) do
|
258
|
+
{ :sort => { name: 1 }}
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'parses a standard filter' do
|
262
|
+
expect(view.filter).to eq('name' => 'test')
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'parses standard options' do
|
266
|
+
expect(view.options).to eq('sort' => { 'name' => 1 }, 'comment' => 'testing')
|
267
|
+
end
|
885
268
|
end
|
886
269
|
|
887
|
-
|
888
|
-
|
270
|
+
context 'when the options contain modifiers' do
|
271
|
+
|
272
|
+
let(:filter) do
|
273
|
+
{ 'name' => 'test' }
|
274
|
+
end
|
275
|
+
|
276
|
+
let(:options) do
|
277
|
+
{ :sort => { name: 1 }, :modifiers => { :$comment => 'testing'}}
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'parses a standard filter' do
|
281
|
+
expect(view.filter).to eq('name' => 'test')
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'parses standard options' do
|
285
|
+
expect(view.options).to eq('sort' => { 'name' => 1 }, 'comment' => 'testing')
|
286
|
+
end
|
889
287
|
end
|
890
288
|
|
891
|
-
context 'when the
|
289
|
+
context 'when the filter and options both contain modifiers' do
|
892
290
|
|
893
|
-
let(:
|
894
|
-
'
|
291
|
+
let(:filter) do
|
292
|
+
{ :$query => { 'name' => 'test' }, :$hint => { name: 1 }}
|
895
293
|
end
|
896
294
|
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
295
|
+
let(:options) do
|
296
|
+
{ :sort => { name: 1 }, :modifiers => { :$comment => 'testing' }}
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'parses a standard filter' do
|
300
|
+
expect(view.filter).to eq('name' => 'test')
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'parses standard options' do
|
304
|
+
expect(view.options).to eq(
|
305
|
+
'sort' => { 'name' => 1 }, 'comment' => 'testing', 'hint' => { 'name' => 1 }
|
306
|
+
)
|
901
307
|
end
|
902
308
|
end
|
903
309
|
end
|
904
310
|
|
905
311
|
describe '#inspect' do
|
906
312
|
|
907
|
-
context 'when there is a namespace,
|
313
|
+
context 'when there is a namespace, filter, and options' do
|
908
314
|
|
909
315
|
let(:options) do
|
910
|
-
{
|
316
|
+
{ 'limit' => 5 }
|
911
317
|
end
|
912
318
|
|
913
|
-
let(:
|
319
|
+
let(:filter) do
|
914
320
|
{ 'name' => 'Emily' }
|
915
321
|
end
|
916
322
|
|
@@ -922,8 +328,8 @@ describe Mongo::Collection::View do
|
|
922
328
|
expect(view.inspect).to match(/.*#{authorized_collection.namespace}.*/)
|
923
329
|
end
|
924
330
|
|
925
|
-
it 'returns a string containing the
|
926
|
-
expect(view.inspect).to match(/.*#{
|
331
|
+
it 'returns a string containing the filter' do
|
332
|
+
expect(view.inspect).to match(/.*#{filter.inspect}.*/)
|
927
333
|
end
|
928
334
|
|
929
335
|
it 'returns a string containing the options' do
|