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
@@ -0,0 +1,144 @@
1
+ description: "Primaries with and without electionIds"
2
+
3
+ uri: "mongodb://a/?replicaSet=rs"
4
+
5
+ phases: [
6
+
7
+ # Primary A has no electionId.
8
+ {
9
+ responses: [
10
+ ["a:27017", {
11
+ ok: 1,
12
+ ismaster: true,
13
+ hosts: ["a:27017", "b:27017", "c:27017"],
14
+ setName: "rs"
15
+ }]
16
+ ],
17
+
18
+ outcome: {
19
+ servers: {
20
+ "a:27017": {
21
+ type: "RSPrimary",
22
+ setName: "rs",
23
+ electionId:
24
+ },
25
+ "b:27017": {
26
+ type: "Unknown",
27
+ setName: ,
28
+ electionId:
29
+ },
30
+ "c:27017": {
31
+ type: "Unknown",
32
+ setName: ,
33
+ electionId:
34
+ }
35
+ },
36
+ topologyType: "ReplicaSetWithPrimary",
37
+ setName: "rs",
38
+ }
39
+ },
40
+
41
+ # B is elected, it has an electionId.
42
+ {
43
+ responses: [
44
+ ["b:27017", {
45
+ ok: 1,
46
+ ismaster: true,
47
+ hosts: ["a:27017", "b:27017", "c:27017"],
48
+ setName: "rs",
49
+ electionId: {"$oid": "000000000000000000000002"}
50
+ }]
51
+ ],
52
+
53
+ outcome: {
54
+ servers: {
55
+ "a:27017": {
56
+ type: "Unknown",
57
+ setName: ,
58
+ electionId:
59
+ },
60
+ "b:27017": {
61
+ type: "RSPrimary",
62
+ setName: "rs",
63
+ electionId: {"$oid": "000000000000000000000002"}
64
+ },
65
+ "c:27017": {
66
+ type: "Unknown",
67
+ setName: ,
68
+ electionId:
69
+ }
70
+ },
71
+ topologyType: "ReplicaSetWithPrimary",
72
+ setName: "rs",
73
+ }
74
+ },
75
+
76
+ # A still claims to be primary, no electionId, we have to trust it.
77
+ {
78
+ responses: [
79
+ ["a:27017", {
80
+ ok: 1,
81
+ ismaster: true,
82
+ hosts: ["a:27017", "b:27017", "c:27017"],
83
+ setName: "rs"
84
+ }]
85
+ ],
86
+ outcome: {
87
+ servers: {
88
+ "a:27017": {
89
+ type: "RSPrimary",
90
+ setName: "rs",
91
+ electionId:
92
+ },
93
+ "b:27017": {
94
+ type: "Unknown",
95
+ setName: ,
96
+ electionId:
97
+ },
98
+ "c:27017": {
99
+ type: "Unknown",
100
+ setName: ,
101
+ electionId:
102
+ }
103
+ },
104
+ topologyType: "ReplicaSetWithPrimary",
105
+ setName: "rs",
106
+ }
107
+ },
108
+
109
+ # But we remember A's electionId, so when we finally hear from C
110
+ # claiming it is primary, we ignore it due to its outdated electionId
111
+ {
112
+ responses: [
113
+ ["c:27017", {
114
+ ok: 1,
115
+ ismaster: true,
116
+ hosts: ["a:27017", "b:27017", "c:27017"],
117
+ setName: "rs",
118
+ electionId: {"$oid": "000000000000000000000001"}
119
+ }]
120
+ ],
121
+ outcome: {
122
+ servers: {
123
+ # Still primary.
124
+ "a:27017": {
125
+ type: "RSPrimary",
126
+ setName: "rs",
127
+ electionId:
128
+ },
129
+ "b:27017": {
130
+ type: "Unknown",
131
+ setName: ,
132
+ electionId:
133
+ },
134
+ "c:27017": {
135
+ type: "Unknown",
136
+ setName: ,
137
+ electionId:
138
+ }
139
+ },
140
+ topologyType: "ReplicaSetWithPrimary",
141
+ setName: "rs",
142
+ }
143
+ }
144
+ ]
@@ -0,0 +1,124 @@
1
+ description: "Disconnected from primary, reject stale primary"
2
+
3
+ uri: "mongodb://a/?replicaSet=rs"
4
+
5
+ phases: [
6
+
7
+ # A is elected, then B.
8
+ {
9
+ responses: [
10
+ ["a:27017", {
11
+ ok: 1,
12
+ ismaster: true,
13
+ hosts: ["a:27017", "b:27017"],
14
+ setName: "rs",
15
+ electionId: {"$oid": "000000000000000000000001"}
16
+ }],
17
+ ["b:27017", {
18
+ ok: 1,
19
+ ismaster: true,
20
+ hosts: ["a:27017", "b:27017"],
21
+ setName: "rs",
22
+ electionId: {"$oid": "000000000000000000000002"}
23
+ }]
24
+ ],
25
+
26
+ outcome: {
27
+ servers: {
28
+ "a:27017": {
29
+ type: "Unknown",
30
+ setName: ,
31
+ electionId:
32
+ },
33
+ "b:27017": {
34
+ type: "RSPrimary",
35
+ setName: "rs",
36
+ electionId: {"$oid": "000000000000000000000002"}
37
+ }
38
+ },
39
+ topologyType: "ReplicaSetWithPrimary",
40
+ setName: "rs",
41
+ }
42
+ },
43
+
44
+ # Disconnected from B.
45
+ {
46
+ responses: [
47
+ ["b:27017", {}]
48
+ ],
49
+ outcome: {
50
+ servers: {
51
+ "a:27017": {
52
+ type: "Unknown",
53
+ setName: ,
54
+ electionId:
55
+ },
56
+ "b:27017": {
57
+ type: "Unknown",
58
+ setName: ,
59
+ electionId:
60
+ }
61
+ },
62
+ topologyType: "ReplicaSetNoPrimary",
63
+ setName: "rs",
64
+ }
65
+ },
66
+
67
+ # A still claims to be primary but it's ignored.
68
+ {
69
+ responses: [
70
+ ["a:27017", {
71
+ ok: 1,
72
+ ismaster: true,
73
+ hosts: ["a:27017", "b:27017"],
74
+ setName: "rs",
75
+ electionId: {"$oid": "000000000000000000000001"}
76
+ }]
77
+ ],
78
+ outcome: {
79
+ servers: {
80
+ "a:27017": {
81
+ type: "Unknown",
82
+ setName: ,
83
+ electionId:
84
+ },
85
+ "b:27017": {
86
+ type: "Unknown",
87
+ setName: ,
88
+ electionId:
89
+ }
90
+ },
91
+ topologyType: "ReplicaSetNoPrimary",
92
+ setName: "rs",
93
+ }
94
+ },
95
+
96
+ # Now A is re-elected.
97
+ {
98
+ responses: [
99
+ ["a:27017", {
100
+ ok: 1,
101
+ ismaster: true,
102
+ hosts: ["a:27017", "b:27017"],
103
+ setName: "rs",
104
+ electionId: {"$oid": "000000000000000000000003"}
105
+ }]
106
+ ],
107
+ outcome: {
108
+ servers: {
109
+ "a:27017": {
110
+ type: "RSPrimary",
111
+ setName: "rs",
112
+ electionId: {"$oid": "000000000000000000000003"}
113
+ },
114
+ "b:27017": {
115
+ type: "Unknown",
116
+ setName: ,
117
+ electionId:
118
+ }
119
+ },
120
+ topologyType: "ReplicaSetWithPrimary",
121
+ setName: "rs",
122
+ }
123
+ }
124
+ ]
@@ -0,0 +1,104 @@
1
+ description: "Mongos disconnect"
2
+
3
+ uri: "mongodb://a,b"
4
+
5
+ phases: [
6
+
7
+ {
8
+ responses: [
9
+
10
+ ["a:27017", {
11
+
12
+ ok: 1,
13
+ ismaster: true,
14
+ msg: "isdbgrid"
15
+ }],
16
+
17
+ ["b:27017", {
18
+
19
+ ok: 1,
20
+ ismaster: true,
21
+ msg: "isdbgrid"
22
+ }]
23
+ ],
24
+
25
+ outcome: {
26
+
27
+ servers: {
28
+
29
+ "a:27017": {
30
+
31
+ type: "Mongos",
32
+ setName:
33
+ },
34
+
35
+ "b:27017": {
36
+
37
+ type: "Mongos",
38
+ setName:
39
+ }
40
+ },
41
+
42
+ topologyType: "Sharded",
43
+ setName:
44
+ }
45
+ },
46
+ {
47
+ responses: [
48
+ ["a:27017", {}], # Hangup.
49
+ ],
50
+
51
+ outcome: {
52
+
53
+ servers: {
54
+
55
+ "a:27017": {
56
+
57
+ type: "Unknown",
58
+ setName:
59
+ },
60
+
61
+ "b:27017": {
62
+
63
+ type: "Mongos",
64
+ setName:
65
+ }
66
+ },
67
+
68
+ topologyType: "Sharded",
69
+ setName:
70
+ }
71
+ },
72
+ {
73
+ responses: [
74
+ # Back in action.
75
+ ["a:27017", {
76
+
77
+ ok: 1,
78
+ ismaster: true,
79
+ msg: "isdbgrid"
80
+ }],
81
+ ],
82
+
83
+ outcome: {
84
+
85
+ servers: {
86
+
87
+ "a:27017": {
88
+
89
+ type: "Mongos",
90
+ setName:
91
+ },
92
+
93
+ "b:27017": {
94
+
95
+ type: "Mongos",
96
+ setName:
97
+ }
98
+ },
99
+
100
+ topologyType: "Sharded",
101
+ setName:
102
+ }
103
+ }
104
+ ]
@@ -45,6 +45,15 @@ module Mongo
45
45
  client.cluster.instance_variable_get(:@servers).detect{ |s| s.address.to_s == uri }
46
46
  end
47
47
 
48
+ # Helper to convert an extended JSON ObjectId electionId to BSON::ObjectId.
49
+ #
50
+ # @since 2.1.0
51
+ def self.convert_election_ids(docs)
52
+ docs.each do |doc |
53
+ doc['electionId'] = BSON::ObjectId.from_string(doc['electionId']['$oid']) if doc['electionId']
54
+ end
55
+ end
56
+
48
57
  # Represents a specification.
49
58
  #
50
59
  # @since 2.0.0
@@ -102,7 +111,7 @@ module Mongo
102
111
  # @since 2.0.0
103
112
  def initialize(phase, uri)
104
113
  @phase = phase
105
- @responses = @phase['responses'].map{ |response| Response.new(response, uri) }
114
+ @responses = @phase['responses'].map{ |response| Response.new(SDAM::convert_election_ids(response), uri) }
106
115
  @outcome = Outcome.new(@phase['outcome'])
107
116
  end
108
117
  end
@@ -158,10 +167,18 @@ module Mongo
158
167
  #
159
168
  # @since 2.0.0
160
169
  def initialize(outcome)
161
- @servers = outcome['servers']
170
+ @servers = process_servers(outcome['servers'])
162
171
  @set_name = outcome['setName']
163
172
  @topology_type = outcome['topologyType']
164
173
  end
174
+
175
+ private
176
+
177
+ def process_servers(servers)
178
+ servers.each do |s|
179
+ SDAM::convert_election_ids([ s[1] ])
180
+ end
181
+ end
165
182
  end
166
183
  end
167
184
  end
@@ -35,7 +35,7 @@ shared_examples 'a bulk write object' do
35
35
  end
36
36
 
37
37
  it 'returns n_inserted of 1' do
38
- expect(bulk.execute[:n_inserted]).to eq(1)
38
+ expect(bulk.execute.inserted_count).to eq(1)
39
39
  end
40
40
 
41
41
  it 'only inserts that document' do
@@ -94,7 +94,7 @@ shared_examples 'a bulk write object' do
94
94
  context 'when multiple documents match delete selector' do
95
95
 
96
96
  it 'reports n_removed correctly' do
97
- expect(bulk.execute[:n_removed]).to eq(1)
97
+ expect(bulk.execute.deleted_count).to eq(1)
98
98
  end
99
99
 
100
100
  it 'deletes only matching documents' do
@@ -136,7 +136,7 @@ shared_examples 'a bulk write object' do
136
136
  context 'when multiple documents match delete selector' do
137
137
 
138
138
  it 'reports n_removed correctly' do
139
- expect(bulk.execute[:n_removed]).to eq(2)
139
+ expect(bulk.execute.deleted_count).to eq(2)
140
140
  end
141
141
 
142
142
  it 'deletes all matching documents' do
@@ -156,7 +156,7 @@ shared_examples 'a bulk write object' do
156
156
  end
157
157
 
158
158
  it 'reports n_removed correctly' do
159
- expect(bulk.execute[:n_removed]).to eq(1)
159
+ expect(bulk.execute.deleted_count).to eq(1)
160
160
  end
161
161
 
162
162
  it 'deletes all matching documents' do
@@ -233,7 +233,7 @@ shared_examples 'a bulk write object' do
233
233
  end
234
234
 
235
235
  it 'reports n_matched correctly' do
236
- expect(bulk.execute[:n_matched]).to eq(1)
236
+ expect(bulk.execute.matched_count).to eq(1)
237
237
  end
238
238
 
239
239
  it 'only applies the replacement to one matching document' do
@@ -260,7 +260,7 @@ shared_examples 'a bulk write object' do
260
260
  end
261
261
 
262
262
  it 'reports n_matched correctly' do
263
- expect(bulk.execute[:n_matched]).to eq(0)
263
+ expect(bulk.execute.matched_count).to eq(0)
264
264
  end
265
265
 
266
266
  it 'does not replace any documents' do
@@ -331,19 +331,19 @@ shared_examples 'a bulk write object' do
331
331
  context 'when a valid update document is specified' do
332
332
 
333
333
  it 'reports n_modified correctly', if: write_command_enabled? do
334
- expect(bulk.execute[:n_modified]).to eq(1)
334
+ expect(bulk.execute.modified_count).to eq(1)
335
335
  end
336
336
 
337
337
  it 'reports n_modified correctly', unless: write_command_enabled? do
338
- expect(bulk.execute[:n_modified]).to eq(nil)
338
+ expect(bulk.execute.modified_count).to eq(nil)
339
339
  end
340
340
 
341
341
  it 'reports n_upserted correctly' do
342
- expect(bulk.execute[:n_upserted]).to eq(0)
342
+ expect(bulk.execute.upserted_count).to eq(0)
343
343
  end
344
344
 
345
345
  it 'reports n_matched correctly' do
346
- expect(bulk.execute[:n_matched]).to eq(1)
346
+ expect(bulk.execute.matched_count).to eq(1)
347
347
  end
348
348
 
349
349
  it 'applies the correct writes' do
@@ -365,19 +365,23 @@ shared_examples 'a bulk write object' do
365
365
  end
366
366
 
367
367
  it 'reports n_modified correctly', if: write_command_enabled? do
368
- expect(bulk.execute[:n_modified]).to eq(0)
368
+ expect(bulk.execute.modified_count).to eq(0)
369
369
  end
370
370
 
371
371
  it 'reports n_modified correctly', unless: write_command_enabled? do
372
- expect(bulk.execute[:n_modified]).to eq(nil)
372
+ expect(bulk.execute.modified_count).to eq(nil)
373
373
  end
374
374
 
375
375
  it 'reports n_upserted correctly' do
376
- expect(bulk.execute[:n_upserted]).to eq(1)
376
+ expect(bulk.execute.upserted_count).to eq(1)
377
+ end
378
+
379
+ it 'returns the upserted ids', if: write_command_enabled? do
380
+ expect(bulk.execute.upserted_ids.size).to eq(1)
377
381
  end
378
382
 
379
383
  it 'reports n_matched correctly' do
380
- expect(bulk.execute[:n_matched]).to eq(0)
384
+ expect(bulk.execute.matched_count).to eq(0)
381
385
  end
382
386
 
383
387
  it 'applies the correct writes' do
@@ -444,19 +448,19 @@ shared_examples 'a bulk write object' do
444
448
  context 'when a valid update document is specified' do
445
449
 
446
450
  it 'reports n_modified correctly', if: write_command_enabled? do
447
- expect(bulk.execute[:n_modified]).to eq(2)
451
+ expect(bulk.execute.modified_count).to eq(2)
448
452
  end
449
453
 
450
454
  it 'reports n_modified correctly', unless: write_command_enabled? do
451
- expect(bulk.execute[:n_modified]).to eq(nil)
455
+ expect(bulk.execute.modified_count).to eq(nil)
452
456
  end
453
457
 
454
458
  it 'reports n_upserted correctly' do
455
- expect(bulk.execute[:n_upserted]).to eq(0)
459
+ expect(bulk.execute.upserted_count).to eq(0)
456
460
  end
457
461
 
458
462
  it 'reports n_matched correctly' do
459
- expect(bulk.execute[:n_matched]).to eq(2)
463
+ expect(bulk.execute.matched_count).to eq(2)
460
464
  end
461
465
 
462
466
  it 'applies the correct writes' do
@@ -478,19 +482,19 @@ shared_examples 'a bulk write object' do
478
482
  end
479
483
 
480
484
  it 'reports n_modified correctly', if: write_command_enabled? do
481
- expect(bulk.execute[:n_modified]).to eq(0)
485
+ expect(bulk.execute.modified_count).to eq(0)
482
486
  end
483
487
 
484
488
  it 'reports n_modified correctly', unless: write_command_enabled? do
485
- expect(bulk.execute[:n_modified]).to eq(nil)
489
+ expect(bulk.execute.modified_count).to eq(nil)
486
490
  end
487
491
 
488
492
  it 'reports n_upserted correctly' do
489
- expect(bulk.execute[:n_upserted]).to eq(1)
493
+ expect(bulk.execute.upserted_count).to eq(1)
490
494
  end
491
495
 
492
496
  it 'reports n_matched correctly' do
493
- expect(bulk.execute[:n_matched]).to eq(0)
497
+ expect(bulk.execute.matched_count).to eq(0)
494
498
  end
495
499
 
496
500
  it 'applies the correct writes' do