mongo 2.16.0 → 2.17.1

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/README.md +1 -1
  4. data/lib/mongo/auth/aws/request.rb +0 -1
  5. data/lib/mongo/client.rb +4 -0
  6. data/lib/mongo/cluster/reapers/cursor_reaper.rb +26 -14
  7. data/lib/mongo/collection/view/aggregation.rb +62 -17
  8. data/lib/mongo/collection/view/builder/aggregation.rb +11 -13
  9. data/lib/mongo/collection/view/builder/map_reduce.rb +8 -5
  10. data/lib/mongo/collection/view/change_stream.rb +7 -3
  11. data/lib/mongo/collection/view/iterable.rb +2 -3
  12. data/lib/mongo/collection/view/map_reduce.rb +16 -1
  13. data/lib/mongo/collection/view/readable.rb +24 -1
  14. data/lib/mongo/collection/view/writable.rb +23 -0
  15. data/lib/mongo/collection.rb +21 -1
  16. data/lib/mongo/cursor/kill_spec.rb +19 -2
  17. data/lib/mongo/cursor.rb +5 -5
  18. data/lib/mongo/database/view.rb +4 -2
  19. data/lib/mongo/database.rb +6 -6
  20. data/lib/mongo/error/snapshot_session_invalid_server_version.rb +31 -0
  21. data/lib/mongo/error/snapshot_session_transaction_prohibited.rb +30 -0
  22. data/lib/mongo/error.rb +2 -0
  23. data/lib/mongo/operation/delete/op_msg.rb +2 -1
  24. data/lib/mongo/operation/find/builder/command.rb +1 -0
  25. data/lib/mongo/operation/result.rb +6 -0
  26. data/lib/mongo/operation/shared/executable.rb +4 -0
  27. data/lib/mongo/operation/shared/sessions_supported.rb +18 -2
  28. data/lib/mongo/operation/update/op_msg.rb +2 -1
  29. data/lib/mongo/server/description/features.rb +3 -1
  30. data/lib/mongo/server/push_monitor.rb +4 -1
  31. data/lib/mongo/server_selector/base.rb +26 -4
  32. data/lib/mongo/session.rb +19 -0
  33. data/lib/mongo/socket/ocsp_cache.rb +2 -3
  34. data/lib/mongo/socket.rb +1 -5
  35. data/lib/mongo/utils.rb +0 -6
  36. data/lib/mongo/version.rb +1 -1
  37. data/mongo.gemspec +1 -1
  38. data/spec/integration/read_preference_spec.rb +16 -12
  39. data/spec/lite_spec_helper.rb +7 -0
  40. data/spec/mongo/cluster/cursor_reaper_spec.rb +22 -15
  41. data/spec/mongo/collection/view/aggregation_spec.rb +71 -95
  42. data/spec/mongo/collection/view/change_stream_spec.rb +1 -1
  43. data/spec/mongo/collection/view/map_reduce_spec.rb +30 -1
  44. data/spec/mongo/cursor_spec.rb +3 -2
  45. data/spec/mongo/operation/read_preference_op_msg_spec.rb +24 -1
  46. data/spec/mongo/server/monitor/connection_spec.rb +22 -0
  47. data/spec/mongo/server/push_monitor_spec.rb +101 -0
  48. data/spec/mongo/server_selector_spec.rb +136 -15
  49. data/spec/mongo/socket/ssl_spec.rb +26 -58
  50. data/spec/mongo/utils_spec.rb +0 -14
  51. data/spec/runners/auth.rb +1 -1
  52. data/spec/runners/change_streams/spec.rb +1 -1
  53. data/spec/runners/cmap.rb +1 -1
  54. data/spec/runners/command_monitoring.rb +1 -1
  55. data/spec/runners/connection_string.rb +1 -1
  56. data/spec/runners/crud/spec.rb +1 -3
  57. data/spec/runners/crud/verifier.rb +1 -2
  58. data/spec/runners/gridfs.rb +1 -1
  59. data/spec/runners/read_write_concern_document.rb +1 -1
  60. data/spec/runners/sdam.rb +1 -1
  61. data/spec/runners/server_selection.rb +1 -1
  62. data/spec/runners/server_selection_rtt.rb +1 -1
  63. data/spec/runners/unified/assertions.rb +3 -1
  64. data/spec/runners/unified/crud_operations.rb +77 -23
  65. data/spec/runners/unified/ddl_operations.rb +29 -1
  66. data/spec/runners/unified/entity_map.rb +3 -3
  67. data/spec/runners/unified/support_operations.rb +6 -1
  68. data/spec/runners/unified/test.rb +15 -3
  69. data/spec/runners/unified/test_group.rb +1 -1
  70. data/spec/spec_tests/data/crud_unified/aggregate-let.yml +138 -0
  71. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +155 -0
  72. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +151 -0
  73. data/spec/spec_tests/data/crud_unified/deleteMany-let.yml +91 -0
  74. data/spec/spec_tests/data/crud_unified/deleteOne-let.yml +89 -0
  75. data/spec/spec_tests/data/crud_unified/find-let.yml +71 -0
  76. data/spec/spec_tests/data/crud_unified/findOneAndDelete-let.yml +88 -0
  77. data/spec/spec_tests/data/crud_unified/findOneAndReplace-let.yml +94 -0
  78. data/spec/spec_tests/data/crud_unified/findOneAndUpdate-let.yml +96 -0
  79. data/spec/spec_tests/data/crud_unified/updateMany-let.yml +103 -0
  80. data/spec/spec_tests/data/crud_unified/updateOne-let.yml +98 -0
  81. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/DefaultNoMaxStaleness.yml +2 -2
  82. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/LastUpdateTime.yml +3 -3
  83. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest.yml +3 -3
  84. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Nearest2.yml +3 -3
  85. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred.yml +2 -2
  86. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/PrimaryPreferred_tags.yml +2 -2
  87. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/Secondary.yml +4 -4
  88. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred.yml +2 -2
  89. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/SecondaryPreferred_tags.yml +4 -4
  90. data/spec/spec_tests/data/max_staleness/ReplicaSetNoPrimary/ZeroMaxStaleness.yml +2 -2
  91. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/DefaultNoMaxStaleness.yml +2 -2
  92. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LastUpdateTime.yml +3 -3
  93. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat.yml +2 -2
  94. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/LongHeartbeat2.yml +2 -2
  95. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessTooSmall.yml +2 -2
  96. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/MaxStalenessWithModePrimary.yml +2 -2
  97. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest.yml +3 -3
  98. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest2.yml +3 -3
  99. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Nearest_tags.yml +2 -2
  100. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/PrimaryPreferred.yml +2 -2
  101. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred.yml +2 -2
  102. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags.yml +5 -5
  103. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/SecondaryPreferred_tags2.yml +3 -3
  104. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags.yml +5 -5
  105. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/Secondary_tags2.yml +3 -3
  106. data/spec/spec_tests/data/max_staleness/ReplicaSetWithPrimary/ZeroMaxStaleness.yml +2 -2
  107. data/spec/spec_tests/data/max_staleness/Sharded/SmallMaxStaleness.yml +2 -2
  108. data/spec/spec_tests/data/max_staleness/Single/SmallMaxStaleness.yml +1 -1
  109. data/spec/spec_tests/data/max_staleness/Unknown/SmallMaxStaleness.yml +1 -1
  110. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-client-error.yml +69 -0
  111. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-not-supported-server-error.yml +102 -0
  112. data/spec/spec_tests/data/sessions_unified/snapshot-sessions-unsupported-ops.yml +258 -0
  113. data/spec/spec_tests/data/sessions_unified/snapshot-sessions.yml +482 -0
  114. data/spec/spec_tests/seed_list_discovery_spec.rb +1 -1
  115. data/spec/spec_tests/sessions_unified_spec.rb +13 -0
  116. data/spec/support/utils.rb +31 -0
  117. data.tar.gz.sig +0 -0
  118. metadata +1127 -1090
  119. metadata.gz.sig +1 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 803953b133578a0014b611609e6b334196ebe25484ee4db3fc3299cf1911445f
4
- data.tar.gz: 368a07676afa5d71f41e86b9a288b4691f99b0549d041d87d6c4a8cf771d6ff5
3
+ metadata.gz: 1a38f748fe8350d12ecfd23a30e794b65addcfbf8f5303504f5f85999e2c2b0d
4
+ data.tar.gz: 876f431a9bfc558ecad0006a32b6ed90b6a94d05ac553a52fbc8b5d3b2b80a55
5
5
  SHA512:
6
- metadata.gz: dd6d240f340e8ea904028bf7d3a9cc2ef6ee6d0e54d181a45c2e083f8e71dc29fab942d265425f5eeb98c0e5f81786f8d0ade460e90ffe2da7af69038f22155f
7
- data.tar.gz: 4474efb5b33f984b4900bd702f05d1c012b5827b09b33281da60c9e07f3c416953292d2d2e9b463ed3c015f8a5e607de9da9aafcf8452b9568373dae49dbd880
6
+ metadata.gz: 256181a9c42fee1b029c899ab56a1a1f5b5283d4071913fc5777ad185f5349a00dc1fa36ac60b9b203a15f1d0857511c551f417f78864a04899e973e8da14b96
7
+ data.tar.gz: 1272cc35779781fe390276007c831e653b64087e1f34b0459e12d8dfea7099dd39be4e06cef347e36fa7222064ba2f267a5be4a48120d6017f4424876123195b
checksums.yaml.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -5,7 +5,7 @@ MongoDB Ruby Driver
5
5
 
6
6
  The officially supported Ruby driver for [MongoDB](https://www.mongodb.org/).
7
7
 
8
- The Ruby driver supports Ruby 2.4-3.0 and JRuby 9.2.
8
+ The Ruby driver supports Ruby 2.5-3.0 and JRuby 9.2.
9
9
 
10
10
 
11
11
  Documentation
@@ -153,7 +153,6 @@ module Mongo
153
153
  'x-mongodb-gs2-cb-flag' => 'n',
154
154
  'x-mongodb-server-nonce' => Base64.encode64(server_nonce).gsub("\n", ''),
155
155
  }
156
- # Hash#compact is available as of Ruby 2.4
157
156
  if session_token
158
157
  headers['x-amz-security-token'] = session_token
159
158
  end
data/lib/mongo/client.rb CHANGED
@@ -887,6 +887,7 @@ module Mongo
887
887
  #
888
888
  # See https://docs.mongodb.com/manual/reference/command/listDatabases/
889
889
  # for more information and usage.
890
+ # @option opts [ Session ] :session The session to use.
890
891
  #
891
892
  # @return [ Array<String> ] The names of the databases.
892
893
  #
@@ -910,6 +911,7 @@ module Mongo
910
911
  #
911
912
  # See https://docs.mongodb.com/manual/reference/command/listDatabases/
912
913
  # for more information and usage.
914
+ # @option opts [ Session ] :session The session to use.
913
915
  #
914
916
  # @return [ Array<Hash> ] The info for each database.
915
917
  #
@@ -930,6 +932,8 @@ module Mongo
930
932
  # @param [ Hash ] filter The filter criteria for getting a list of databases.
931
933
  # @param [ Hash ] opts The command options.
932
934
  #
935
+ # @option opts [ Session ] :session The session to use.
936
+ #
933
937
  # @return [ Array<Mongo::Database> ] The list of database objects.
934
938
  #
935
939
  # @since 2.5.0
@@ -44,6 +44,7 @@ module Mongo
44
44
  @to_kill = {}
45
45
  @active_cursor_ids = Set.new
46
46
  @mutex = Mutex.new
47
+ @kill_spec_queue = Queue.new
47
48
  end
48
49
 
49
50
  attr_reader :cluster
@@ -51,17 +52,10 @@ module Mongo
51
52
  # Schedule a kill cursors operation to be eventually executed.
52
53
  #
53
54
  # @param [ Cursor::KillSpec ] kill_spec The kill specification.
54
- # @param [ Mongo::Server ] server The server to send the kill cursors
55
- # operation to.
56
55
  #
57
56
  # @api private
58
- def schedule_kill_cursor(kill_spec, server)
59
- @mutex.synchronize do
60
- if @active_cursor_ids.include?(kill_spec.cursor_id)
61
- @to_kill[server.address.seed] ||= Set.new
62
- @to_kill[server.address.seed] << kill_spec
63
- end
64
- end
57
+ def schedule_kill_cursor(kill_spec)
58
+ @kill_spec_queue << kill_spec
65
59
  end
66
60
 
67
61
  # Register a cursor id as active.
@@ -110,6 +104,24 @@ module Mongo
110
104
  end
111
105
  end
112
106
 
107
+ # Read and decode scheduled kill cursors operations.
108
+ #
109
+ # This method mutates instance variables without locking, so is is not
110
+ # thread safe. Generally, it should not be called itself, this is a helper
111
+ # for `kill_cursor` method.
112
+ #
113
+ # @api private
114
+ def read_scheduled_kill_specs
115
+ while kill_spec = @kill_spec_queue.pop(true)
116
+ if @active_cursor_ids.include?(kill_spec.cursor_id)
117
+ @to_kill[kill_spec.server_address] ||= Set.new
118
+ @to_kill[kill_spec.server_address] << kill_spec
119
+ end
120
+ end
121
+ rescue ThreadError
122
+ # Empty queue, nothing to do.
123
+ end
124
+
113
125
  # Execute all pending kill cursors operations.
114
126
  #
115
127
  # @example Execute pending kill cursors operations.
@@ -122,14 +134,14 @@ module Mongo
122
134
  # TODO optimize this to batch kill cursor operations for the same
123
135
  # server/database/collection instead of killing each cursor
124
136
  # individually.
125
-
126
137
  loop do
127
- server_address_str = nil
138
+ server_address = nil
128
139
 
129
140
  kill_spec = @mutex.synchronize do
141
+ read_scheduled_kill_specs
130
142
  # Find a server that has any cursors scheduled for destruction.
131
- server_address_str, specs =
132
- @to_kill.detect { |server_address_str, specs| specs.any? }
143
+ server_address, specs =
144
+ @to_kill.detect { |_, specs| specs.any? }
133
145
 
134
146
  if specs.nil?
135
147
  # All servers have empty specs, nothing to do.
@@ -168,7 +180,7 @@ module Mongo
168
180
  op = Operation::KillCursors.new(spec)
169
181
 
170
182
  server = cluster.servers.detect do |server|
171
- server.address.seed == server_address_str
183
+ server.address == server_address
172
184
  end
173
185
 
174
186
  unless server
@@ -73,6 +73,25 @@ module Mongo
73
73
  # @param [ Array<Hash> ] pipeline The pipeline of operations.
74
74
  # @param [ Hash ] options The aggregation options.
75
75
  #
76
+ # @option options [ true, false ] :allow_disk_use Set to true if disk
77
+ # usage is allowed during the aggregation.
78
+ # @option options [ Integer ] :batch_size The number of documents to return
79
+ # per batch.
80
+ # @option options [ true, false ] :bypass_document_validation Whether or
81
+ # not to skip document level validation.
82
+ # @option options [ Hash ] :collation The collation to use.
83
+ # @option options [ String ] :comment Associate a comment with the aggregation.
84
+ # @option options [ String ] :hint The index to use for the aggregation.
85
+ # @option options [ Hash ] :let Mapping of variables to use in the pipeline.
86
+ # See the server documentation for details.
87
+ # @option options [ Integer ] :max_time_ms The maximum amount of time in
88
+ # milliseconds to allow the aggregation to run.
89
+ # @option options [ true, false ] :use_cursor Indicates whether the command
90
+ # will request that the server provide results using a cursor. Note that
91
+ # as of server version 3.6, aggregations always provide results using a
92
+ # cursor and this option is therefore not valid.
93
+ # @option options [ Session ] :session The session to use.
94
+ #
76
95
  # @since 2.0.0
77
96
  def initialize(view, pipeline, options = {})
78
97
  @view = view
@@ -108,37 +127,63 @@ module Mongo
108
127
  @view.send(:server_selector)
109
128
  end
110
129
 
111
- def aggregate_spec(session)
112
- Builder::Aggregation.new(pipeline, view, options.merge(session: session)).specification
130
+ def aggregate_spec(server, session, read_preference)
131
+ Builder::Aggregation.new(
132
+ pipeline,
133
+ view,
134
+ options.merge(session: session, read_preference: read_preference)
135
+ ).specification
113
136
  end
114
137
 
115
138
  def new(options)
116
139
  Aggregation.new(view, pipeline, options)
117
140
  end
118
141
 
119
- def initial_query_op(session)
120
- Operation::Aggregate.new(aggregate_spec(session))
142
+ def initial_query_op(server, session, read_preference)
143
+ Operation::Aggregate.new(aggregate_spec(server, session, read_preference))
121
144
  end
122
145
 
123
- def valid_server?(server)
124
- if secondary_ok?
125
- true
146
+ # Return effective read preference for the operation.
147
+ #
148
+ # If the pipeline contains $merge or $out, and read preference specified
149
+ # by user is secondary or secondary_preferred, and selected server is below
150
+ # 5.0, than this method returns primary read preference, because the
151
+ # aggregation will be routed to primary. Otherwise return the original
152
+ # read preference.
153
+ #
154
+ # See https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#read-preferences-and-server-selection
155
+ #
156
+ # @param [ Server ] server The server on which the operation
157
+ # should be executed.
158
+ # @return [ Hash | nil ] read preference hash that should be sent with
159
+ # this command.
160
+ def effective_read_preference(server)
161
+ return unless view.read_preference
162
+ return view.read_preference unless write?
163
+ return view.read_preference unless [:secondary, :secondary_preferred].include?(view.read_preference[:mode])
164
+
165
+ primary_read_preference = {mode: :primary}
166
+ if server.primary?
167
+ log_warn("Routing the Aggregation operation to the primary server")
168
+ primary_read_preference
169
+ elsif server.mongos? && !server.features.merge_out_on_secondary_enabled?
170
+ log_warn("Routing the Aggregation operation to the primary server")
171
+ primary_read_preference
126
172
  else
127
- description = server.description
128
- description.standalone? || description.mongos? || description.primary? || description.load_balancer?
173
+ view.read_preference
129
174
  end
130
- end
131
175
 
132
- def secondary_ok?
133
- !write?
134
176
  end
135
177
 
136
178
  def send_initial_query(server, session)
137
- unless valid_server?(server)
138
- log_warn("Rerouting the Aggregation operation to the primary server - #{server.summary} is not suitable")
139
- server = cluster.next_primary(nil, session)
140
- end
141
- initial_query_op(session).execute(server, context: Operation::Context.new(client: client, session: session))
179
+ initial_query_op(
180
+ server,
181
+ session,
182
+ effective_read_preference(server)
183
+ ).execute(
184
+ server,
185
+ context: Operation::Context.new(client: client, session: session)
186
+ )
142
187
  end
143
188
 
144
189
  # Skip, sort, limit, projection are specified as pipeline stages
@@ -30,16 +30,17 @@ module Mongo
30
30
  #
31
31
  # @since 2.2.0
32
32
  MAPPINGS = BSON::Document.new(
33
- :allow_disk_use => 'allowDiskUse',
34
- :max_time_ms => 'maxTimeMS',
33
+ allow_disk_use: 'allowDiskUse',
34
+ bypass_document_validation: 'bypassDocumentValidation',
35
+ explain: 'explain',
36
+ collation: 'collation',
37
+ comment: 'comment',
38
+ hint: 'hint',
39
+ let: 'let',
35
40
  # This is intentional; max_await_time_ms is an alias for maxTimeMS
36
41
  # used on getMore commands for change streams.
37
- :max_await_time_ms => 'maxTimeMS',
38
- :explain => 'explain',
39
- :bypass_document_validation => 'bypassDocumentValidation',
40
- :collation => 'collation',
41
- :hint => 'hint',
42
- :comment => 'comment'
42
+ max_await_time_ms: 'maxTimeMS',
43
+ max_time_ms: 'maxTimeMS',
43
44
  ).freeze
44
45
 
45
46
  def_delegators :@view, :collection, :database, :read, :write_concern
@@ -55,12 +56,9 @@ module Mongo
55
56
 
56
57
  # Initialize the builder.
57
58
  #
58
- # @example Initialize the builder.
59
- # Aggregation.new(map, reduce, view, options)
60
- #
61
59
  # @param [ Array<Hash> ] pipeline The aggregation pipeline.
62
60
  # @param [ Collection::View ] view The collection view.
63
- # @param [ Hash ] options The map/reduce options.
61
+ # @param [ Hash ] options The map/reduce and read preference options.
64
62
  #
65
63
  # @since 2.2.0
66
64
  def initialize(pipeline, view, options)
@@ -81,7 +79,7 @@ module Mongo
81
79
  spec = {
82
80
  selector: aggregation_command,
83
81
  db_name: database.name,
84
- read: view.read_preference,
82
+ read: @options[:read_preference] || view.read_preference,
85
83
  session: @options[:session],
86
84
  collation: @options[:collation],
87
85
  }
@@ -114,12 +114,15 @@ module Mongo
114
114
  collection.read_concern)
115
115
  end
116
116
  command.update(view_options)
117
- command.update(Utils.slice_hash(options, :collation))
117
+ command.update(options.slice(:collation))
118
+
118
119
  # Read preference isn't simply passed in the command payload
119
- # (it may need to be converted to wire protocol flags)
120
- # so remove it here and hopefully it's handled elsewhere.
121
- # If not, RUBY-2706.
122
- command.delete(:read)
120
+ # (it may need to be converted to wire protocol flags).
121
+ # Ideally it should be removed here, however due to Mongoid 7
122
+ # using this method and requiring :read to be returned from it,
123
+ # we cannot do this just yet - see RUBY-2932.
124
+ #command.delete(:read)
125
+
123
126
  command.merge!(Options::Mapper.transform_documents(options, MAPPINGS))
124
127
  command
125
128
  end
@@ -298,8 +298,8 @@ module Mongo
298
298
  [{ '$changeStream' => change_doc }] + @change_stream_filters
299
299
  end
300
300
 
301
- def aggregate_spec(session)
302
- super(session).tap do |spec|
301
+ def aggregate_spec(server, session, read_preference)
302
+ super(server, session, read_preference).tap do |spec|
303
303
  spec[:selector][:aggregate] = 1 unless for_collection?
304
304
  end
305
305
  end
@@ -349,7 +349,11 @@ module Mongo
349
349
  end
350
350
 
351
351
  def send_initial_query(server, session)
352
- initial_query_op(session).execute(server, context: Operation::Context.new(client: client, session: session))
352
+ initial_query_op(server, session, view.read_preference)
353
+ .execute(
354
+ server,
355
+ context: Operation::Context.new(client: client, session: session)
356
+ )
353
357
  end
354
358
 
355
359
  def time_to_bson_timestamp(time)
@@ -114,11 +114,9 @@ module Mongo
114
114
 
115
115
  def select_cursor(session)
116
116
  if respond_to?(:write?, true) && write?
117
- server = server_selector.select_server(cluster, nil, session)
117
+ server = server_selector.select_server(cluster, nil, session, write_aggregation: true)
118
118
  result = send_initial_query(server, session)
119
119
 
120
- # RUBY-2367: This will be updated to allow the query cache to
121
- # cache cursors with multi-batch results.
122
120
  if use_query_cache?
123
121
  CachingCursor.new(view, result, server, session: session)
124
122
  else
@@ -161,6 +159,7 @@ module Mongo
161
159
  collation: collation,
162
160
  sort: sort,
163
161
  skip: skip,
162
+ let: options[:let],
164
163
  limit: limit,
165
164
  allow_disk_use: options[:allow_disk_use],
166
165
  read: read,
@@ -115,6 +115,8 @@ module Mongo
115
115
  @map_function = map.dup.freeze
116
116
  @reduce_function = reduce.dup.freeze
117
117
  @options = BSON::Document.new(options).freeze
118
+
119
+ client.log_warn('The map_reduce operation is deprecated, please use the aggregation pipeline instead')
118
120
  end
119
121
 
120
122
  # Set or get the jsMode flag for the operation.
@@ -248,7 +250,20 @@ module Mongo
248
250
  end
249
251
 
250
252
  def initial_query_op(session)
251
- Operation::MapReduce.new(map_reduce_spec(session))
253
+ spec = map_reduce_spec(session)
254
+ # Read preference isn't simply passed in the command payload
255
+ # (it may need to be converted to wire protocol flags).
256
+ # Passing it in command payload produces errors on at least
257
+ # 5.0 mongoses.
258
+ # In the future map_reduce_command should remove :read
259
+ # from its return value, however we cannot do this right now
260
+ # due to Mongoid 7 relying on :read being returned as part of
261
+ # the command - see RUBY-2932.
262
+ # Delete :read here for now because it cannot be sent to mongos this way.
263
+ spec = spec.dup
264
+ spec[:selector] = spec[:selector].dup
265
+ spec[:selector].delete(:read)
266
+ Operation::MapReduce.new(spec)
252
267
  end
253
268
 
254
269
  def valid_server?(server)
@@ -34,6 +34,25 @@ module Mongo
34
34
  # @param [ Array<Hash> ] pipeline The aggregation pipeline.
35
35
  # @param [ Hash ] options The aggregation options.
36
36
  #
37
+ # @option options [ true, false ] :allow_disk_use Set to true if disk
38
+ # usage is allowed during the aggregation.
39
+ # @option options [ Integer ] :batch_size The number of documents to return
40
+ # per batch.
41
+ # @option options [ true, false ] :bypass_document_validation Whether or
42
+ # not to skip document level validation.
43
+ # @option options [ Hash ] :collation The collation to use.
44
+ # @option options [ String ] :comment Associate a comment with the aggregation.
45
+ # @option options [ String ] :hint The index to use for the aggregation.
46
+ # @option options [ Hash ] :let Mapping of variables to use in the pipeline.
47
+ # See the server documentation for details.
48
+ # @option options [ Integer ] :max_time_ms The maximum amount of time in
49
+ # milliseconds to allow the aggregation to run.
50
+ # @option options [ true, false ] :use_cursor Indicates whether the command
51
+ # will request that the server provide results using a cursor. Note that
52
+ # as of server version 3.6, aggregations always provide results using a
53
+ # cursor and this option is therefore not valid.
54
+ # @option options [ Session ] :session The session to use.
55
+ #
37
56
  # @return [ Aggregation ] The aggregation object.
38
57
  #
39
58
  # @since 2.0.0
@@ -242,7 +261,11 @@ module Mongo
242
261
  {'$collStats' => {'count' => {}}},
243
262
  {'$group' => {'_id' => 1, 'n' => {'$sum' => '$count'}}},
244
263
  ]
245
- spec = Builder::Aggregation.new(pipeline, self, options.merge(session: session)).specification
264
+ spec = Builder::Aggregation.new(
265
+ pipeline,
266
+ self,
267
+ options.merge(session: session)
268
+ ).specification
246
269
  result = Operation::Aggregate.new(spec).execute(server, context: context)
247
270
  result.documents.first.fetch('n')
248
271
  else
@@ -48,6 +48,8 @@ module Mongo
48
48
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
49
49
  # @option opts [ Hash ] :write_concern The write concern options.
50
50
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
51
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
52
+ # See the server documentation for details.
51
53
  #
52
54
  # @return [ BSON::Document, nil ] The document, if found.
53
55
  #
@@ -75,6 +77,7 @@ module Mongo
75
77
  bypassDocumentValidation: opts[:bypass_document_validation],
76
78
  hint: opts[:hint],
77
79
  collation: opts[:collation] || opts['collation'] || collation,
80
+ let: opts[:let]
78
81
  }.compact
79
82
 
80
83
  write_with_retry(session, write_concern) do |server, txn_num|
@@ -109,6 +112,8 @@ module Mongo
109
112
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
110
113
  # @option opts [ Hash ] :write_concern The write concern options.
111
114
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
115
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
116
+ # See the server documentation for details.
112
117
  #
113
118
  # @return [ BSON::Document ] The document.
114
119
  #
@@ -142,6 +147,8 @@ module Mongo
142
147
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
143
148
  # @option opts [ Hash ] :write_concern The write concern options.
144
149
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
150
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
151
+ # See the server documentation for details.
145
152
  #
146
153
  # @return [ BSON::Document ] The document.
147
154
  #
@@ -172,6 +179,7 @@ module Mongo
172
179
  bypassDocumentValidation: opts[:bypass_document_validation],
173
180
  hint: opts[:hint],
174
181
  collation: opts[:collation] || opts['collation'] || collation,
182
+ let: opts[:let],
175
183
  }.compact
176
184
 
177
185
  write_with_retry(session, write_concern) do |server, txn_num|
@@ -200,6 +208,8 @@ module Mongo
200
208
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
201
209
  # @option opts [ Hash ] :write_concern The write concern options.
202
210
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
211
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
212
+ # See the server documentation for details.
203
213
  #
204
214
  # @return [ Result ] The response from the database.
205
215
  #
@@ -232,6 +242,7 @@ module Mongo
232
242
  write_concern: write_concern,
233
243
  bypass_document_validation: !!opts[:bypass_document_validation],
234
244
  session: session,
245
+ let: opts[:let],
235
246
  ).execute(server, context: Operation::Context.new(client: client, session: session))
236
247
  end
237
248
  end
@@ -250,6 +261,8 @@ module Mongo
250
261
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
251
262
  # @option opts [ Hash ] :write_concern The write concern options.
252
263
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
264
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
265
+ # See the server documentation for details.
253
266
  #
254
267
  # @return [ Result ] The response from the database.
255
268
  #
@@ -283,6 +296,7 @@ module Mongo
283
296
  bypass_document_validation: !!opts[:bypass_document_validation],
284
297
  session: session,
285
298
  txn_num: txn_num,
299
+ let: opts[:let],
286
300
  ).execute(server, context: Operation::Context.new(client: client, session: session))
287
301
  end
288
302
  end
@@ -306,6 +320,8 @@ module Mongo
306
320
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
307
321
  # @option opts [ Hash ] :write_concern The write concern options.
308
322
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
323
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
324
+ # See the server documentation for details.
309
325
  #
310
326
  # @return [ Result ] The response from the database.
311
327
  #
@@ -343,6 +359,7 @@ module Mongo
343
359
  bypass_document_validation: !!opts[:bypass_document_validation],
344
360
  session: session,
345
361
  txn_num: txn_num,
362
+ let: opts[:let]
346
363
  ).execute(server, context: Operation::Context.new(client: client, session: session))
347
364
  end
348
365
  end
@@ -368,6 +385,8 @@ module Mongo
368
385
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
369
386
  # @option opts [ Hash ] :write_concern The write concern options.
370
387
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
388
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
389
+ # See the server documentation for details.
371
390
  #
372
391
  # @return [ Result ] The response from the database.
373
392
  #
@@ -405,6 +424,7 @@ module Mongo
405
424
  write_concern: write_concern,
406
425
  bypass_document_validation: !!opts[:bypass_document_validation],
407
426
  session: session,
427
+ let: opts[:let],
408
428
  ).execute(server, context: Operation::Context.new(client: client, session: session))
409
429
  end
410
430
  end
@@ -430,6 +450,8 @@ module Mongo
430
450
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
431
451
  # @option opts [ Hash ] :write_concern The write concern options.
432
452
  # Can be :w => Integer, :fsync => Boolean, :j => Boolean.
453
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
454
+ # See the server documentation for details.
433
455
  #
434
456
  # @return [ Result ] The response from the database.
435
457
  #
@@ -467,6 +489,7 @@ module Mongo
467
489
  bypass_document_validation: !!opts[:bypass_document_validation],
468
490
  session: session,
469
491
  txn_num: txn_num,
492
+ let: opts[:let],
470
493
  ).execute(server, context: Operation::Context.new(client: client, session: session))
471
494
  end
472
495
  end
@@ -253,7 +253,7 @@ module Mongo
253
253
  options = Hash[self.options.reject do |key, value|
254
254
  %w(read read_preference read_concern).include?(key.to_s)
255
255
  end]
256
- options.update(Utils.slice_hash(opts, *TIME_SERIES_OPTIONS.keys))
256
+ options.update(opts.slice(*TIME_SERIES_OPTIONS.keys))
257
257
  # Converting Ruby spelled time series options to server style.
258
258
  TIME_SERIES_OPTIONS.each do |ruby_key, server_key|
259
259
  if options.key?(ruby_key)
@@ -361,6 +361,8 @@ module Mongo
361
361
  # @option options [ Integer ] :skip The number of docs to skip before returning results.
362
362
  # @option options [ Hash ] :sort The key and direction pairs by which the result set
363
363
  # will be sorted.
364
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
365
+ # See the server documentation for details.
364
366
  #
365
367
  # @return [ CollectionView ] The collection view.
366
368
  #
@@ -386,6 +388,8 @@ module Mongo
386
388
  # @option options [ Hash ] :collation The collation to use.
387
389
  # @option options [ String ] :comment Associate a comment with the aggregation.
388
390
  # @option options [ String ] :hint The index to use for the aggregation.
391
+ # @option options [ Hash ] :let Mapping of variables to use in the pipeline.
392
+ # See the server documentation for details.
389
393
  # @option options [ Integer ] :max_time_ms The maximum amount of time in
390
394
  # milliseconds to allow the aggregation to run.
391
395
  # @option options [ true, false ] :use_cursor Indicates whether the command
@@ -666,6 +670,8 @@ module Mongo
666
670
  # @option options [ Session ] :session The session to use.
667
671
  # @option options [ Hash | String ] :hint The index to use for this operation.
668
672
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
673
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
674
+ # See the server documentation for details.
669
675
  #
670
676
  # @return [ Result ] The response from the database.
671
677
  #
@@ -686,6 +692,8 @@ module Mongo
686
692
  # @option options [ Session ] :session The session to use.
687
693
  # @option options [ Hash | String ] :hint The index to use for this operation.
688
694
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
695
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
696
+ # See the server documentation for details.
689
697
  #
690
698
  # @return [ Result ] The response from the database.
691
699
  #
@@ -734,6 +742,8 @@ module Mongo
734
742
  # @option options [ Session ] :session The session to use.
735
743
  # @option options [ Hash | String ] :hint The index to use for this operation.
736
744
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
745
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
746
+ # See the server documentation for details.
737
747
  #
738
748
  # @return [ Result ] The response from the database.
739
749
  #
@@ -761,6 +771,8 @@ module Mongo
761
771
  # @option options [ Session ] :session The session to use.
762
772
  # @option options [ Hash | String ] :hint The index to use for this operation.
763
773
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
774
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
775
+ # See the server documentation for details.
764
776
  #
765
777
  # @return [ Result ] The response from the database.
766
778
  #
@@ -788,6 +800,8 @@ module Mongo
788
800
  # @option options [ Session ] :session The session to use.
789
801
  # @option options [ Hash | String ] :hint The index to use for this operation.
790
802
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
803
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
804
+ # See the server documentation for details.
791
805
  #
792
806
  # @return [ Result ] The response from the database.
793
807
  #
@@ -816,6 +830,8 @@ module Mongo
816
830
  # @option options [ Session ] :session The session to use.
817
831
  # @option options [ Hash | String ] :hint The index to use for this operation.
818
832
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
833
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
834
+ # See the server documentation for details.
819
835
  #
820
836
  # @return [ BSON::Document, nil ] The document, if found.
821
837
  #
@@ -854,6 +870,8 @@ module Mongo
854
870
  # @option options [ Session ] :session The session to use.
855
871
  # @option options [ Hash | String ] :hint The index to use for this operation.
856
872
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
873
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
874
+ # See the server documentation for details.
857
875
  #
858
876
  # @return [ BSON::Document ] The document.
859
877
  #
@@ -890,6 +908,8 @@ module Mongo
890
908
  # @option options [ Session ] :session The session to use.
891
909
  # @option options [ Hash | String ] :hint The index to use for this operation.
892
910
  # May be specified as a Hash (e.g. { _id: 1 }) or a String (e.g. "_id_").
911
+ # @option options [ Hash ] :let Mapping of variables to use in the command.
912
+ # See the server documentation for details.
893
913
  #
894
914
  # @return [ BSON::Document ] The document.
895
915
  #