Skip to content

Commit 2d9f021

Browse files
p-mongop
andauthored
RUBY-2220 Move find command construction code into operations layer
(#2275) * RUBY-2220 Move find command construction code into operations layer * fix explain test on old sharded cluster servers * remove read preference * 2706 again Co-authored-by: Oleg Pudeyev <code@olegp.name>
1 parent aab776e commit 2d9f021

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+919
-621
lines changed

docs/reference/crud-operations.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,32 @@ when querying and their corresponding methods as examples.
260260
# MongoDB 2.6
261261
client[:artists].find.explain(verbose: true)
262262

263+
The explain operation supports ``:session`` and ``:read``
264+
(for read preference) options. To specify these options for a single
265+
explain operation, they must be given to the ``find`` method as
266+
follows:
267+
268+
.. code-block:: ruby
269+
270+
client[:artists].find({}, session: session).explain
271+
272+
client[:artists].find({}, read: {mode: :secondary_preferred}).explain
273+
274+
If the read preference option is specified on the client or on the
275+
collection, it will be passed to the explain operation:
276+
277+
.. code-block:: ruby
278+
279+
client[:artists, read: {mode: :secondary_preferred}].find.explain
280+
281+
Note that the session option is not accepted when creating a collection
282+
object.
283+
284+
The explain command does not support passing the read concern option.
285+
If the read concern is specifed on the client or collection level, or
286+
if the read concern is specified as a find option, it will NOT be passed
287+
by the driver to the explain command.
288+
263289
.. note::
264290

265291
The information returned by the server for the ``explain`` command

lib/mongo/collection.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ def create(opts = {})
237237
# TODO put the list of read options in a class-level constant when
238238
# we figure out what the full set of them is.
239239
options = Hash[self.options.reject do |key, value|
240-
%w(read read_preference).include?(key.to_s)
240+
%w(read read_preference read_concern).include?(key.to_s)
241241
end]
242242
operation = { :create => name }.merge(options)
243243
operation.delete(:write)
@@ -253,12 +253,12 @@ def create(opts = {})
253253
raise Error::UnsupportedCollation
254254
end
255255

256-
Operation::Create.new({
257-
selector: operation,
258-
db_name: database.name,
259-
write_concern: write_concern,
260-
session: session,
261-
}).execute(server, context: Operation::Context.new(client: client, session: session))
256+
Operation::Create.new(
257+
selector: operation,
258+
db_name: database.name,
259+
write_concern: write_concern,
260+
session: session,
261+
).execute(server, context: Operation::Context.new(client: client, session: session))
262262
end
263263
end
264264

@@ -332,8 +332,8 @@ def drop(opts = {})
332332
# @option options [ true, false ] :no_cursor_timeout The server normally times out idle
333333
# cursors after an inactivity period (10 minutes) to prevent excess memory use.
334334
# Set this option to prevent that.
335-
# @option options [ true, false ] :oplog_replay Internal replication use only - driver
336-
# should not set.
335+
# @option options [ true, false ] :oplog_replay For internal replication
336+
# use only, applications should not set this option.
337337
# @option options [ Hash ] :projection The fields to include or exclude from each doc
338338
# in the result set.
339339
# @option options [ Session ] :session The session to use.

lib/mongo/collection/view.rb

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ def hash
141141
# @option options [ Hash ] :read The read preference to use for the
142142
# query. If none is provided, the collection's default read preference
143143
# is used.
144+
# @option options [ Hash ] :read_concern The read concern to use for
145+
# the query.
144146
# @option options [ true | false ] :show_disk_loc Return disk location
145147
# info as a field in each doc.
146148
# @option options [ Integer ] :skip The number of documents to skip.
@@ -153,7 +155,19 @@ def hash
153155
def initialize(collection, filter = {}, options = {})
154156
validate_doc!(filter)
155157
@collection = collection
156-
parse_parameters!(BSON::Document.new(filter), BSON::Document.new(options))
158+
159+
filter = BSON::Document.new(filter)
160+
options = BSON::Document.new(options)
161+
162+
# This is when users pass $query in filter and other modifiers
163+
# alongside?
164+
query = filter.delete(:$query)
165+
# This makes modifiers contain the filter if filter wasn't
166+
# given via $query but as top-level keys, presumably
167+
# downstream code ignores non-modifier keys in the modifiers?
168+
modifiers = filter.merge(options.delete(:modifiers) || {})
169+
@filter = (query || filter).freeze
170+
@options = Operation::Find::Builder::Modifiers.map_driver_options(modifiers).merge!(options).freeze
157171
end
158172

159173
# Get a human-readable string representation of +View+.
@@ -189,13 +203,6 @@ def initialize_copy(other)
189203
@filter = other.filter.dup
190204
end
191205

192-
def parse_parameters!(filter, options)
193-
query = filter.delete(QUERY)
194-
modifiers = (filter || {}).merge(options.delete(MODIFIERS) || {})
195-
@filter = (query || filter).freeze
196-
@options = Builder::Modifiers.map_driver_options(modifiers).merge!(options).freeze
197-
end
198-
199206
def new(options)
200207
View.new(collection, filter, options)
201208
end

lib/mongo/collection/view/builder.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,3 @@
1717

1818
require 'mongo/collection/view/builder/aggregation'
1919
require 'mongo/collection/view/builder/map_reduce'
20-
require 'mongo/collection/view/builder/op_query'
21-
require 'mongo/collection/view/builder/find_command'
22-
require 'mongo/collection/view/builder/flags'
23-
require 'mongo/collection/view/builder/modifiers'

lib/mongo/collection/view/builder/find_command.rb

Lines changed: 0 additions & 173 deletions
This file was deleted.

lib/mongo/collection/view/builder/map_reduce.rb

Lines changed: 9 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -71,36 +71,6 @@ def initialize(map, reduce, view, options)
7171
@options = options
7272
end
7373

74-
# Get the specification for issuing a find command on the map/reduce
75-
# results.
76-
#
77-
# @example Get the command specification.
78-
# builder.command_specification
79-
#
80-
# @return [ Hash ] The specification.
81-
#
82-
# @since 2.2.0
83-
def command_specification
84-
{
85-
selector: find_command,
86-
db_name: query_database,
87-
read: read,
88-
session: options[:session]
89-
}
90-
end
91-
92-
# Get the specification for the document query after a map/reduce.
93-
#
94-
# @example Get the query specification.
95-
# builder.query_specification
96-
#
97-
# @return [ Hash ] The specification.
98-
#
99-
# @since 2.2.0
100-
def query_specification
101-
{ selector: {}, options: {}, db_name: query_database, coll_name: query_collection }
102-
end
103-
10474
# Get the specification to pass to the map/reduce operation.
10575
#
10676
# @example Get the specification.
@@ -113,6 +83,8 @@ def specification
11383
spec = {
11484
selector: map_reduce_command,
11585
db_name: database.name,
86+
# Note that selector just above may also have a read preference
87+
# specified, per the #map_reduce_command method below.
11688
read: read,
11789
session: options[:session]
11890
}
@@ -121,46 +93,36 @@ def specification
12193

12294
private
12395

124-
OUT_ACTIONS = [ :replace, :merge, :reduce ].freeze
125-
12696
def write?(spec)
12797
if out = spec[:selector][:out]
12898
out.is_a?(String) ||
12999
(out.respond_to?(:keys) && out.keys.first.to_s.downcase != View::MapReduce::INLINE)
130100
end
131101
end
132102

133-
def find_command
134-
BSON::Document.new('find' => query_collection, 'filter' => {})
135-
end
136-
137103
def map_reduce_command
138104
command = BSON::Document.new(
139105
:mapReduce => collection.name,
140106
:map => map,
141107
:reduce => reduce,
142108
:query => filter,
143-
:out => { inline: 1 }
109+
:out => { inline: 1 },
144110
)
111+
# Shouldn't this use self.read ?
145112
if collection.read_concern
146113
command[:readConcern] = Options::Mapper.transform_values_to_strings(
147114
collection.read_concern)
148115
end
149116
command.merge!(view_options)
117+
# Read preference isn't simply passed in the command payload
118+
# (it may need to be converted to wire protocol flags)
119+
# so remove it here and hopefully it's handled elsewhere.
120+
# If not, RUBY-2706.
121+
command.delete(:read)
150122
command.merge!(Options::Mapper.transform_documents(options, MAPPINGS))
151123
command
152124
end
153125

154-
def query_database
155-
options[:out].respond_to?(:keys) && options[:out][:db] ? options[:out][:db] : database.name
156-
end
157-
158-
def query_collection
159-
if options[:out].respond_to?(:keys)
160-
options[:out][OUT_ACTIONS.find { |action| options[:out][action] }]
161-
end || options[:out]
162-
end
163-
164126
def view_options
165127
@view_options ||= (opts = view.options.dup
166128
opts.delete(:session)

0 commit comments

Comments
 (0)