mongo 2.0.6 → 2.1.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/mongo.rb +2 -0
  5. data/lib/mongo/bulk_write.rb +1 -0
  6. data/lib/mongo/bulk_write/bulk_writable.rb +87 -31
  7. data/lib/mongo/bulk_write/deletable.rb +8 -7
  8. data/lib/mongo/bulk_write/insertable.rb +4 -3
  9. data/lib/mongo/bulk_write/ordered_bulk_write.rb +6 -6
  10. data/lib/mongo/bulk_write/replacable.rb +4 -3
  11. data/lib/mongo/bulk_write/result.rb +138 -0
  12. data/lib/mongo/bulk_write/unordered_bulk_write.rb +5 -8
  13. data/lib/mongo/bulk_write/updatable.rb +8 -7
  14. data/lib/mongo/client.rb +36 -4
  15. data/lib/mongo/cluster.rb +39 -4
  16. data/lib/mongo/cluster/topology/replica_set.rb +20 -4
  17. data/lib/mongo/cluster/topology/sharded.rb +1 -1
  18. data/lib/mongo/collection.rb +282 -29
  19. data/lib/mongo/collection/view/aggregation.rb +32 -4
  20. data/lib/mongo/collection/view/iterable.rb +2 -1
  21. data/lib/mongo/collection/view/map_reduce.rb +3 -1
  22. data/lib/mongo/collection/view/readable.rb +89 -14
  23. data/lib/mongo/collection/view/writable.rb +11 -5
  24. data/lib/mongo/cursor.rb +11 -3
  25. data/lib/mongo/dbref.rb +113 -0
  26. data/lib/mongo/error.rb +6 -2
  27. data/lib/mongo/error/parser.rb +1 -1
  28. data/lib/mongo/event/description_changed.rb +1 -1
  29. data/lib/mongo/grid/file.rb +1 -1
  30. data/lib/mongo/grid/fs.rb +2 -5
  31. data/lib/mongo/monitoring.rb +199 -0
  32. data/lib/mongo/monitoring/command_log_subscriber.rb +88 -0
  33. data/lib/mongo/monitoring/event.rb +17 -0
  34. data/lib/mongo/monitoring/event/command_failed.rb +96 -0
  35. data/lib/mongo/monitoring/event/command_started.rb +88 -0
  36. data/lib/mongo/monitoring/event/command_succeeded.rb +96 -0
  37. data/lib/mongo/monitoring/publishable.rb +96 -0
  38. data/lib/mongo/operation.rb +1 -0
  39. data/lib/mongo/operation/executable.rb +1 -1
  40. data/lib/mongo/operation/parallel_scan.rb +76 -0
  41. data/lib/mongo/operation/parallel_scan/result.rb +72 -0
  42. data/lib/mongo/operation/specifiable.rb +18 -0
  43. data/lib/mongo/operation/write/bulk/bulk_delete.rb +1 -1
  44. data/lib/mongo/operation/write/bulk/bulk_insert.rb +1 -1
  45. data/lib/mongo/operation/write/bulk/bulk_mergable.rb +2 -2
  46. data/lib/mongo/operation/write/bulk/bulk_update.rb +1 -1
  47. data/lib/mongo/operation/write/bulk/bulk_update/result.rb +13 -1
  48. data/lib/mongo/protocol/delete.rb +8 -13
  49. data/lib/mongo/protocol/get_more.rb +13 -13
  50. data/lib/mongo/protocol/insert.rb +8 -13
  51. data/lib/mongo/protocol/kill_cursors.rb +7 -11
  52. data/lib/mongo/protocol/query.rb +58 -20
  53. data/lib/mongo/protocol/reply.rb +12 -0
  54. data/lib/mongo/protocol/update.rb +13 -14
  55. data/lib/mongo/server.rb +23 -2
  56. data/lib/mongo/server/connectable.rb +0 -22
  57. data/lib/mongo/server/connection.rb +29 -0
  58. data/lib/mongo/server/description.rb +23 -1
  59. data/lib/mongo/server/monitor.rb +17 -1
  60. data/lib/mongo/server/monitor/connection.rb +24 -0
  61. data/lib/mongo/socket/ssl.rb +28 -16
  62. data/lib/mongo/socket/tcp.rb +1 -1
  63. data/lib/mongo/socket/unix.rb +1 -1
  64. data/lib/mongo/uri.rb +12 -5
  65. data/lib/mongo/version.rb +1 -1
  66. data/spec/mongo/auth/cr_spec.rb +9 -1
  67. data/spec/mongo/auth/ldap_spec.rb +9 -1
  68. data/spec/mongo/auth/scram_spec.rb +9 -1
  69. data/spec/mongo/auth/x509_spec.rb +9 -1
  70. data/spec/mongo/{bulk/bulk_write_spec.rb → bulk_write_spec.rb} +15 -15
  71. data/spec/mongo/client_spec.rb +42 -0
  72. data/spec/mongo/cluster/topology/replica_set_spec.rb +16 -9
  73. data/spec/mongo/cluster/topology/sharded_spec.rb +11 -3
  74. data/spec/mongo/cluster/topology/single_spec.rb +12 -4
  75. data/spec/mongo/cluster_spec.rb +55 -10
  76. data/spec/mongo/collection/view/aggregation_spec.rb +123 -1
  77. data/spec/mongo/collection/view/explainable_spec.rb +1 -1
  78. data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
  79. data/spec/mongo/collection/view/readable_spec.rb +251 -6
  80. data/spec/mongo/collection/view/writable_spec.rb +4 -4
  81. data/spec/mongo/collection/view_spec.rb +233 -71
  82. data/spec/mongo/collection_spec.rb +905 -9
  83. data/spec/mongo/crud_spec.rb +2 -2
  84. data/spec/mongo/cursor_spec.rb +3 -3
  85. data/spec/mongo/dbref_spec.rb +149 -0
  86. data/spec/mongo/monitoring_spec.rb +168 -0
  87. data/spec/mongo/operation/map_reduce_spec.rb +1 -1
  88. data/spec/mongo/operation/write/bulk/bulk_delete_spec.rb +1 -1
  89. data/spec/mongo/operation/write/bulk/bulk_insert_spec.rb +2 -2
  90. data/spec/mongo/operation/write/bulk/bulk_update_spec.rb +1 -1
  91. data/spec/mongo/operation/write/delete_spec.rb +1 -1
  92. data/spec/mongo/operation/write/insert_spec.rb +2 -2
  93. data/spec/mongo/operation/write/update_spec.rb +1 -1
  94. data/spec/mongo/protocol/query_spec.rb +0 -29
  95. data/spec/mongo/server/connection_pool_spec.rb +18 -6
  96. data/spec/mongo/server/connection_spec.rb +12 -4
  97. data/spec/mongo/server/description_spec.rb +7 -3
  98. data/spec/mongo/server/monitor_spec.rb +30 -0
  99. data/spec/mongo/server_discovery_and_monitoring_spec.rb +11 -4
  100. data/spec/mongo/server_selection_spec.rb +14 -6
  101. data/spec/mongo/server_spec.rb +27 -8
  102. data/spec/mongo/socket/ssl_spec.rb +94 -8
  103. data/spec/mongo/uri_spec.rb +25 -9
  104. data/spec/spec_helper.rb +29 -20
  105. data/spec/support/authorization.rb +19 -4
  106. data/spec/support/certificates/client.pem +4 -4
  107. data/spec/support/crud/read.rb +9 -10
  108. data/spec/support/crud/write.rb +24 -20
  109. data/spec/support/sdam/rs/equal_electionids.yml +45 -0
  110. data/spec/support/sdam/rs/new_primary_new_electionid.yml +98 -0
  111. data/spec/support/sdam/rs/null_election_id.yml +144 -0
  112. data/spec/support/sdam/rs/primary_disconnect_electionid.yml +124 -0
  113. data/spec/support/sdam/sharded/mongos_disconnect.yml +104 -0
  114. data/spec/support/server_discovery_and_monitoring.rb +19 -2
  115. data/spec/support/shared/bulk_write.rb +26 -22
  116. data/spec/support/shared/server_selector.rb +2 -1
  117. metadata +31 -7
  118. metadata.gz.sig +0 -0
  119. data/lib/mongo/error/invalid_uri_option.rb +0 -38
@@ -15,7 +15,7 @@ describe Mongo::Collection::View::Explainable do
15
15
  end
16
16
 
17
17
  after do
18
- authorized_collection.find.delete_many
18
+ authorized_collection.delete_many
19
19
  end
20
20
 
21
21
  describe '#explain' do
@@ -48,7 +48,7 @@ describe Mongo::Collection::View::MapReduce do
48
48
  end
49
49
 
50
50
  after do
51
- authorized_collection.find.delete_many
51
+ authorized_collection.delete_many
52
52
  end
53
53
 
54
54
  let(:map_reduce) do
@@ -15,7 +15,7 @@ describe Mongo::Collection::View::Readable do
15
15
  end
16
16
 
17
17
  after do
18
- authorized_collection.find.delete_many
18
+ authorized_collection.delete_many
19
19
  end
20
20
 
21
21
  describe '#allow_partial_results' do
@@ -75,6 +75,21 @@ describe Mongo::Collection::View::Readable do
75
75
  end
76
76
  end
77
77
  end
78
+
79
+ context 'when options are specified' do
80
+
81
+ let(:agg_options) do
82
+ { :max_time_ms => 500 }
83
+ end
84
+
85
+ let(:aggregation) do
86
+ view.aggregate(pipeline, agg_options)
87
+ end
88
+
89
+ it 'passes the option to the Aggregation object' do
90
+ expect(aggregation.options[:max_time_ms]).to eq(agg_options[:max_time_ms])
91
+ end
92
+ end
78
93
  end
79
94
 
80
95
  describe '#map_reduce' do
@@ -200,7 +215,7 @@ describe Mongo::Collection::View::Readable do
200
215
  end
201
216
 
202
217
  after do
203
- authorized_collection.find.delete_many
218
+ authorized_collection.delete_many
204
219
  end
205
220
 
206
221
  context 'when a selector is provided' do
@@ -224,6 +239,16 @@ describe Mongo::Collection::View::Readable do
224
239
  it 'takes a read preference option' do
225
240
  expect(view.count(read: { mode: :secondary })).to eq(10)
226
241
  end
242
+
243
+ it 'takes a max_time_ms option', if: write_command_enabled? do
244
+ expect {
245
+ view.count(max_time_ms: 0.1)
246
+ }.to raise_error(Mongo::Error::OperationFailure)
247
+ end
248
+
249
+ it 'sets the max_time_ms option on the command', if: write_command_enabled? do
250
+ expect(view.count(max_time_ms: 100)).to eq(10)
251
+ end
227
252
  end
228
253
 
229
254
  describe '#distinct' do
@@ -338,6 +363,27 @@ describe Mongo::Collection::View::Readable do
338
363
  expect(distinct).to eq([ 'test1', 'test2', 'test3' ])
339
364
  end
340
365
  end
366
+
367
+ context 'when a max_time_ms is specified', if: write_command_enabled? do
368
+
369
+ let(:documents) do
370
+ (1..3).map{ |i| { field: "test" }}
371
+ end
372
+
373
+ before do
374
+ authorized_collection.insert_many(documents)
375
+ end
376
+
377
+ it 'sets the max_time_ms option on the command' do
378
+ expect {
379
+ view.distinct(:field, max_time_ms: 0.1)
380
+ }.to raise_error(Mongo::Error::OperationFailure)
381
+ end
382
+
383
+ it 'sets the max_time_ms option on the command' do
384
+ expect(view.distinct(:field, max_time_ms: 100)).to eq([ 'test' ])
385
+ end
386
+ end
341
387
  end
342
388
 
343
389
  describe '#hint' do
@@ -434,6 +480,41 @@ describe Mongo::Collection::View::Readable do
434
480
  end
435
481
  end
436
482
 
483
+ describe '#parallel_scan', unless: sharded? do
484
+
485
+ let(:documents) do
486
+ (1..200).map do |i|
487
+ { name: "testing-scan-#{i}" }
488
+ end
489
+ end
490
+
491
+ before do
492
+ authorized_collection.insert_many(documents)
493
+ end
494
+
495
+ let(:cursors) do
496
+ view.parallel_scan(2)
497
+ end
498
+
499
+ it 'returns an array of cursors', if: write_command_enabled? do
500
+ cursors.each do |cursor|
501
+ expect(cursor.class).to be(Mongo::Cursor)
502
+ end
503
+ end
504
+
505
+ it 'returns the correct number of documents', if: write_command_enabled? do
506
+ expect(
507
+ cursors.reduce(0) { |total, cursor| total + cursor.to_a.size }
508
+ ).to eq(200)
509
+ end
510
+
511
+ it 'raises an error', unless: write_command_enabled? do
512
+ expect {
513
+ cursors
514
+ }.to raise_error(Mongo::Error::OperationFailure)
515
+ end
516
+ end
517
+
437
518
  describe '#projection' do
438
519
 
439
520
  let(:options) do
@@ -479,6 +560,15 @@ describe Mongo::Collection::View::Readable do
479
560
 
480
561
  describe '#read' do
481
562
 
563
+ context 'when providing a hash' do
564
+
565
+ it 'converts to a read preference' do
566
+ expect(view.read(:mode => :primary_preferred).read).to be_a(
567
+ Mongo::ServerSelector::PrimaryPreferred
568
+ )
569
+ end
570
+ end
571
+
482
572
  context 'when a read pref is specified' do
483
573
 
484
574
  let(:options) do
@@ -524,12 +614,91 @@ describe Mongo::Collection::View::Readable do
524
614
 
525
615
  describe '#show_disk_loc' do
526
616
 
527
- let(:new_view) do
528
- view.show_disk_loc(true)
617
+ let(:options) do
618
+ { :show_disk_loc => true }
529
619
  end
530
620
 
531
- it 'sets the value in the options' do
532
- expect(new_view.show_disk_loc).to be true
621
+ context 'when show_disk_loc is specified' do
622
+
623
+ let(:new_show_disk_loc) do
624
+ false
625
+ end
626
+
627
+ it 'sets the show_disk_loc value' do
628
+ new_view = view.show_disk_loc(new_show_disk_loc)
629
+ expect(new_view.show_disk_loc).to eq(new_show_disk_loc)
630
+ end
631
+
632
+ it 'returns a new View' do
633
+ expect(view.show_disk_loc(new_show_disk_loc)).not_to be(view)
634
+ end
635
+ end
636
+
637
+ context 'when show_disk_loc is not specified' do
638
+
639
+ it 'returns the show_disk_loc value' do
640
+ expect(view.show_disk_loc).to eq(options[:show_disk_loc])
641
+ end
642
+ end
643
+ end
644
+
645
+ describe '#modifiers' do
646
+
647
+ let(:options) do
648
+ { :modifiers => { :$orderby => Mongo::Index::ASCENDING } }
649
+ end
650
+
651
+ context 'when a modifiers document is specified' do
652
+
653
+ let(:new_modifiers) do
654
+ { :modifiers => { :$orderby => Mongo::Index::DESCENDING } }
655
+ end
656
+
657
+ it 'sets the new_modifiers document' do
658
+ new_view = view.modifiers(new_modifiers)
659
+ expect(new_view.modifiers).to eq(new_modifiers)
660
+ end
661
+
662
+ it 'returns a new View' do
663
+ expect(view.modifiers(new_modifiers)).not_to be(view)
664
+ end
665
+ end
666
+
667
+ context 'when a modifiers document is not specified' do
668
+
669
+ it 'returns the modifiers value' do
670
+ expect(view.modifiers).to eq(options[:modifiers])
671
+ end
672
+ end
673
+ end
674
+
675
+ describe '#max_time_ms' do
676
+
677
+ let(:options) do
678
+ { :max_time_ms => 200 }
679
+ end
680
+
681
+ context 'when max_time_ms is specified' do
682
+
683
+ let(:new_max_time_ms) do
684
+ 300
685
+ end
686
+
687
+ it 'sets the max_time_ms value' do
688
+ new_view = view.max_time_ms(new_max_time_ms)
689
+ expect(new_view.max_time_ms).to eq(new_max_time_ms)
690
+ end
691
+
692
+ it 'returns a new View' do
693
+ expect(view.max_time_ms(new_max_time_ms)).not_to be(view)
694
+ end
695
+ end
696
+
697
+ context 'when max_time_ms is not specified' do
698
+
699
+ it 'returns the max_time_ms value' do
700
+ expect(view.max_time_ms).to eq(options[:max_time_ms])
701
+ end
533
702
  end
534
703
  end
535
704
 
@@ -610,5 +779,81 @@ describe Mongo::Collection::View::Readable do
610
779
  expect(view.sort).to eq(options[:sort])
611
780
  end
612
781
  end
782
+
783
+ context 'when an option is a cursor flag' do
784
+
785
+ let(:query_spec_options) do
786
+ view.send(:query_spec)[:options]
787
+ end
788
+
789
+ context 'when allow_partial_results is set as an option' do
790
+
791
+ let(:options) do
792
+ { :allow_partial_results => true }
793
+ end
794
+
795
+ it 'sets the cursor flag' do
796
+ expect(query_spec_options[:flags]).to eq([:partial])
797
+ end
798
+
799
+ context 'when allow_partial_results is also called as a method' do
800
+
801
+ before do
802
+ view.allow_partial_results
803
+ end
804
+
805
+ it 'sets only one cursor flag' do
806
+ expect(query_spec_options[:flags]).to eq([:partial])
807
+ end
808
+ end
809
+ end
810
+
811
+ context 'when oplog_replay is set as an option' do
812
+
813
+ let(:options) do
814
+ { :oplog_replay => true }
815
+ end
816
+
817
+ it 'sets the cursor flag' do
818
+ expect(query_spec_options[:flags]).to eq([:oplog_replay])
819
+ end
820
+ end
821
+
822
+ context 'when no_cursor_timeout is set as an option' do
823
+
824
+ let(:options) do
825
+ { :no_cursor_timeout => true }
826
+ end
827
+
828
+ it 'sets the cursor flag' do
829
+ expect(query_spec_options[:flags]).to eq([:no_cursor_timeout])
830
+ end
831
+ end
832
+
833
+ context 'when cursor_type is set as an option' do
834
+
835
+ context 'when :tailable is the cursor type' do
836
+
837
+ let(:options) do
838
+ { :cursor_type => :tailable }
839
+ end
840
+
841
+ it 'sets the cursor flag' do
842
+ expect(query_spec_options[:flags]).to eq([:tailable_cursor])
843
+ end
844
+ end
845
+
846
+ context 'when :tailable_await is the cursor type' do
847
+
848
+ let(:options) do
849
+ { :cursor_type => :tailable_await }
850
+ end
851
+
852
+ it 'sets the cursor flags' do
853
+ expect(query_spec_options[:flags]).to eq([:await_data, :tailable_cursor])
854
+ end
855
+ end
856
+ end
857
+ end
613
858
  end
614
859
  end
@@ -15,7 +15,7 @@ describe Mongo::Collection::View::Writable do
15
15
  end
16
16
 
17
17
  after do
18
- authorized_collection.find.delete_many
18
+ authorized_collection.delete_many
19
19
  end
20
20
 
21
21
  describe '#find_one_and_delete' do
@@ -456,11 +456,11 @@ describe Mongo::Collection::View::Writable do
456
456
  context 'when a selector was provided' do
457
457
 
458
458
  let(:selector) do
459
- { field: 'test1' }
459
+ { field: 'test' }
460
460
  end
461
461
 
462
462
  before do
463
- authorized_collection.insert_many([{ field: 'test1' }, { field: 'test2' }])
463
+ authorized_collection.insert_many([{ field: 'test' }, { field: 'test' }])
464
464
  end
465
465
 
466
466
  let!(:response) do
@@ -472,7 +472,7 @@ describe Mongo::Collection::View::Writable do
472
472
  end
473
473
 
474
474
  it 'returns the number updated' do
475
- expect(response.written_count).to eq(1)
475
+ expect(response.written_count).to eq(2)
476
476
  end
477
477
 
478
478
  it 'updates the documents in the collection' do
@@ -15,7 +15,7 @@ describe Mongo::Collection::View do
15
15
  end
16
16
 
17
17
  after do
18
- authorized_collection.find.delete_many
18
+ authorized_collection.delete_many
19
19
  end
20
20
 
21
21
  describe '#==' do
@@ -116,32 +116,38 @@ describe Mongo::Collection::View do
116
116
  end
117
117
 
118
118
  after do
119
- authorized_collection.find.delete_many
119
+ authorized_collection.delete_many
120
120
  end
121
121
 
122
122
  context 'when sending the initial query' do
123
123
 
124
+ let(:returned) do
125
+ view.to_a
126
+ end
127
+
128
+ let(:query_spec) do
129
+ view.send(:query_spec)
130
+ end
131
+
124
132
  context 'when limit is specified' do
125
133
 
126
134
  let(:options) do
127
135
  { :limit => 5 }
128
136
  end
129
137
 
130
- before do
131
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
132
- expect(spec[:options][:limit]).to eq(options[:limit])
133
- end.and_call_original
134
- end
135
-
136
138
  let(:returned) do
137
139
  view.to_a
138
140
  end
139
141
 
142
+ it 'sets the limit on the initial query' do
143
+ expect(query_spec[:options][:limit]).to eq(options[:limit])
144
+ end
145
+
140
146
  it 'returns limited documents' do
141
147
  expect(returned.count).to eq(5)
142
148
  end
143
149
 
144
- it 'allows iteration of the documents' do
150
+ it 'iterates over all of the documents' do
145
151
  returned.each do |doc|
146
152
  expect(doc).to have_key('field')
147
153
  end
@@ -154,21 +160,19 @@ describe Mongo::Collection::View do
154
160
  { :batch_size => 5 }
155
161
  end
156
162
 
157
- before do
158
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
159
- expect(spec[:options][:limit]).to eq(options[:batch_size])
160
- end.and_call_original
161
- end
162
-
163
163
  let(:returned) do
164
164
  view.to_a
165
165
  end
166
166
 
167
+ it 'sets the batch size on the initial query' do
168
+ expect(query_spec[:options][:limit]).to eq(options[:batch_size])
169
+ end
170
+
167
171
  it 'returns all the documents' do
168
172
  expect(returned.count).to eq(10)
169
173
  end
170
174
 
171
- it 'allows iteration of all documents' do
175
+ it 'iterates over all of the documents' do
172
176
  returned.each do |doc|
173
177
  expect(doc).to have_key('field')
174
178
  end
@@ -177,21 +181,15 @@ describe Mongo::Collection::View do
177
181
 
178
182
  context 'when no limit is specified' do
179
183
 
180
- before do
181
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
182
- expect(spec[:options][:limit]).to eq(nil)
183
- end.and_call_original
184
- end
185
-
186
- let(:returned) do
187
- view.to_a
184
+ it 'does not set a limit on the initial query' do
185
+ expect(query_spec[:options][:limit]).to be_nil
188
186
  end
189
187
 
190
188
  it 'returns all the documents' do
191
189
  expect(returned.count).to eq(10)
192
190
  end
193
191
 
194
- it 'allows iteration of all documents' do
192
+ it 'iterates over all of the documents' do
195
193
  returned.each do |doc|
196
194
  expect(doc).to have_key('field')
197
195
  end
@@ -204,21 +202,19 @@ describe Mongo::Collection::View do
204
202
  { :batch_size => 5, :limit => 3 }
205
203
  end
206
204
 
207
- before do
208
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
209
- expect(spec[:options][:limit]).to eq(options[:limit])
210
- end.and_call_original
211
- end
212
-
213
205
  let(:returned) do
214
206
  view.to_a
215
207
  end
216
208
 
209
+ it 'sets the limit on the initial query' do
210
+ expect(query_spec[:options][:limit]).to eq(options[:limit])
211
+ end
212
+
217
213
  it 'returns the limit of documents' do
218
214
  expect(returned.count).to eq(3)
219
215
  end
220
216
 
221
- it 'allows iteration of the documents' do
217
+ it 'iterates over all of the documents' do
222
218
  returned.each do |doc|
223
219
  expect(doc).to have_key('field')
224
220
  end
@@ -231,21 +227,19 @@ describe Mongo::Collection::View do
231
227
  { :limit => 5, :batch_size => 3 }
232
228
  end
233
229
 
234
- before do
235
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
236
- expect(spec[:options][:limit]).to eq(options[:batch_size])
237
- end.and_call_original
238
- end
239
-
240
230
  let(:returned) do
241
231
  view.to_a
242
232
  end
243
233
 
234
+ it 'sets the batch size on the initial query' do
235
+ expect(query_spec[:options][:limit]).to eq(options[:batch_size])
236
+ end
237
+
244
238
  it 'returns the limit of documents' do
245
239
  expect(returned.count).to eq(5)
246
240
  end
247
241
 
248
- it 'allows iteration of the documents' do
242
+ it 'iterates over all of the documents' do
249
243
  returned.each do |doc|
250
244
  expect(doc).to have_key('field')
251
245
  end
@@ -254,20 +248,22 @@ describe Mongo::Collection::View do
254
248
 
255
249
  context 'when the selector has special fields' do
256
250
 
257
- context 'when a snapshot option is provided' do
251
+ context 'when a snapshot option is specified' do
258
252
 
259
253
  let(:options) do
260
254
  { :snapshot => true }
261
255
  end
262
256
 
263
257
  before do
264
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
265
- expect(spec[:selector][:$query]).to eq(selector)
266
- end.and_call_original
258
+ expect(view).to receive(:special_selector).and_call_original
267
259
  end
268
260
 
269
261
  it 'creates a special query selector' do
270
- view.each do |doc|
262
+ expect(query_spec[:selector][:$snapshot]).to eq(options[:snapshot])
263
+ end
264
+
265
+ it 'iterates over all of the documents' do
266
+ returned.each do |doc|
271
267
  expect(doc).to have_key('field')
272
268
  end
273
269
  end
@@ -280,13 +276,36 @@ describe Mongo::Collection::View do
280
276
  end
281
277
 
282
278
  before do
283
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
284
- expect(spec[:selector][:$query]).to eq(selector)
285
- end.and_call_original
279
+ expect(view).to receive(:special_selector).and_call_original
286
280
  end
287
281
 
288
282
  it 'creates a special query selector' do
289
- view.each do |doc|
283
+ expect(query_spec[:selector][:$maxScan]).to eq(options[:max_scan])
284
+ end
285
+
286
+ it 'iterates over all of the documents' do
287
+ returned.each do |doc|
288
+ expect(doc).to have_key('field')
289
+ end
290
+ end
291
+ end
292
+
293
+ context 'when a max_time_ms option is provided' do
294
+
295
+ let(:options) do
296
+ { :max_time_ms => 100 }
297
+ end
298
+
299
+ before do
300
+ expect(view).to receive(:special_selector).and_call_original
301
+ end
302
+
303
+ it 'creates a special query selector' do
304
+ expect(query_spec[:selector][:$maxTimeMS]).to eq(options[:max_time_ms])
305
+ end
306
+
307
+ it 'iterates over all of the documents' do
308
+ returned.each do |doc|
290
309
  expect(doc).to have_key('field')
291
310
  end
292
311
  end
@@ -299,15 +318,16 @@ describe Mongo::Collection::View do
299
318
  end
300
319
 
301
320
  before do
302
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
303
- expect(spec[:selector][:$query]).to eq(selector)
304
- end.and_call_original
321
+ expect(view).to receive(:special_selector).and_call_original
305
322
  end
306
323
 
307
324
  it 'creates a special query selector' do
308
- view.each do |doc|
325
+ expect(query_spec[:selector][:$showDiskLoc]).to eq(options[:show_disk_loc])
326
+ end
327
+
328
+ it 'iterates over all of the documents' do
329
+ returned.each do |doc|
309
330
  expect(doc).to have_key('field')
310
- break
311
331
  end
312
332
  end
313
333
  end
@@ -320,13 +340,15 @@ describe Mongo::Collection::View do
320
340
  end
321
341
 
322
342
  before do
323
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
324
- expect(spec[:selector][:$query]).to eq(selector)
325
- end.and_call_original
343
+ expect(view).to receive(:special_selector).and_call_original
326
344
  end
327
345
 
328
346
  it 'creates a special query selector' do
329
- view.each do |doc|
347
+ expect(query_spec[:selector][:$orderby]).to eq(options[:sort])
348
+ end
349
+
350
+ it 'iterates over all of the documents' do
351
+ returned.each do |doc|
330
352
  expect(doc).to have_key('field')
331
353
  end
332
354
  end
@@ -341,15 +363,11 @@ describe Mongo::Collection::View do
341
363
  end
342
364
 
343
365
  before do
344
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
345
- expect(spec[:selector][:$query]).to eq(selector)
346
- end.and_call_original
366
+ expect(view).to receive(:special_selector).and_call_original
347
367
  end
348
368
 
349
- it'creates a special query selector' do
350
- expect {
351
- view.to_a
352
- }.to raise_error(Mongo::Error::OperationFailure)
369
+ it 'creates a special query selector' do
370
+ expect(query_spec[:selector][:$hint]).to eq(options[:hint])
353
371
  end
354
372
  end
355
373
  end
@@ -361,32 +379,176 @@ describe Mongo::Collection::View do
361
379
  end
362
380
 
363
381
  before do
364
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
365
- expect(spec[:selector][:$query]).to eq(selector)
366
- end.and_call_original
382
+ expect(view).to receive(:special_selector).and_call_original
367
383
  end
368
384
 
369
385
  it 'creates a special query selector' do
386
+ expect(query_spec[:selector][:$comment]).to eq(options[:comment])
387
+ end
388
+
389
+ it 'iterates over all of the documents' do
390
+ returned.each do |doc|
391
+ expect(doc).to have_key('field')
392
+ end
393
+ end
394
+ end
395
+
396
+ context 'when the cluster is sharded', if: sharded? do
397
+
398
+ before do
399
+ allow(authorized_collection.cluster).to receive(:sharded?).and_return(true)
400
+ expect(view).to receive(:special_selector).and_call_original
401
+ end
402
+
403
+ it 'iterates over all of the documents' do
370
404
  view.each do |doc|
371
405
  expect(doc).to have_key('field')
372
406
  end
373
407
  end
374
408
  end
375
409
 
376
- context 'when the cluster is sharded' do
410
+ context 'when a modifier document is provided' do
411
+
412
+ let(:options) do
413
+ { :modifiers => {
414
+ :$orderby => {'x' => Mongo::Index::ASCENDING }
415
+ }
416
+ }
417
+ end
377
418
 
378
419
  before do
379
- expect(Mongo::Operation::Read::Query).to receive(:new) do |spec|
380
- expect(spec[:selector][:$query]).to eq(selector)
381
- end.and_call_original
420
+ expect(view).to receive(:special_selector).and_call_original
382
421
  end
383
422
 
384
423
  it 'creates a special query selector' do
424
+ expect(query_spec[:selector][:$orderby]).to eq(options[:modifiers][:$orderby])
425
+ end
426
+
427
+ it 'iterates over all of the documents' do
385
428
  view.each do |doc|
386
429
  expect(doc).to have_key('field')
387
430
  end
388
431
  end
432
+
433
+ context 'when $explain is specified' do
434
+ let(:options) do
435
+ { :modifiers => {
436
+ :$explain => 1
437
+ }
438
+ }
439
+ end
440
+
441
+ let(:explain) do
442
+ view.to_a.first
443
+ end
444
+
445
+ it 'executes an explain' do
446
+ expect(explain['cursor'] == 'BasicCursor' ||
447
+ explain['queryPlanner']).to be_truthy
448
+ end
449
+
450
+ end
451
+
452
+ context 'when an option is also provided' do
453
+
454
+ context 'when $orderby and sort are specified' do
455
+
456
+ let(:options) do
457
+ { :modifiers => {
458
+ :$orderby => { 'x' => Mongo::Index::ASCENDING }
459
+ },
460
+ :sort => { 'x' => Mongo::Index::DESCENDING }
461
+ }
462
+ end
463
+
464
+ it 'overrides the modifier value with the option value' do
465
+ expect(query_spec[:selector][:$orderby]).to eq(options[:sort])
466
+ end
467
+ end
468
+
469
+ context 'when $comment and comment are specified' do
470
+
471
+ let(:options) do
472
+ { :modifiers => {
473
+ :$comment => 'query1'
474
+ },
475
+ :comment => 'query2'
476
+ }
477
+ end
478
+
479
+ it 'overrides the modifier value with the option value' do
480
+ expect(query_spec[:selector][:$comment]).to eq(options[:comment])
481
+ end
482
+ end
483
+
484
+ context 'when $hint and hint are specified' do
485
+
486
+ let(:options) do
487
+ { :modifiers => {
488
+ :$hint => 'x'
489
+ },
490
+ :hint => 'y'
491
+ }
492
+ end
493
+
494
+ it 'overrides the modifier value with the option value' do
495
+ expect(query_spec[:selector][:$hint]).to eq(options[:hint])
496
+ end
497
+
498
+ end
499
+
500
+ context 'when $maxScan and max_scan are specified' do
501
+
502
+ let(:options) do
503
+ { :modifiers => {
504
+ :$maxScan => 4
505
+ },
506
+ :max_scan => 5
507
+ }
508
+ end
509
+
510
+ it 'overrides the modifier value with the option value' do
511
+ expect(query_spec[:selector][:$maxScan]).to eq(options[:max_scan])
512
+ end
513
+ end
514
+
515
+ context 'when $maxTimeMS and max_time_ms are specified' do
516
+
517
+ let(:options) do
518
+ { :modifiers => {
519
+ :$maxTimeMS => 100
520
+ },
521
+ :max_time_ms => 200
522
+ }
523
+ end
524
+
525
+ it 'overrides the modifier value with the option value' do
526
+ expect(query_spec[:selector][:$maxTimeMS]).to eq(options[:max_time_ms])
527
+ end
528
+ end
529
+
530
+ context 'when $query and a selector are specified' do
531
+
532
+ let(:selector) do
533
+ { 'y' => 1 }
534
+ end
535
+
536
+ let(:options) do
537
+ { :modifiers => {
538
+ :$query => { 'field' => 1 }
539
+ }
540
+ }
541
+ end
542
+
543
+ it 'overrides the modifier value with the option value' do
544
+ expect(query_spec[:selector][:$query]).to eq(selector)
545
+ end
546
+ end
547
+
548
+
549
+ end
389
550
  end
551
+
390
552
  end
391
553
 
392
554
  context 'when there are no special fields' do