mongo 2.0.6 → 2.1.0.beta

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.
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