1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
# Copyright (C) 2015-2017 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module Mongo
class Collection
class View
module Builder
# Builds a find command specification from options.
#
# @since 2.2.0
class FindCommand
extend Forwardable
# The mappings from ruby options to the find command.
#
# @since 2.2.0
MAPPINGS = BSON::Document.new(
sort: 'sort',
projection: 'projection',
hint: 'hint',
skip: 'skip',
limit: 'limit',
batch_size: 'batchSize',
single_batch: 'singleBatch',
comment: 'comment',
max_scan: 'maxScan',
max_time_ms: 'maxTimeMS',
max_value: 'max',
min_value: 'min',
return_key: 'returnKey',
show_disk_loc: 'showRecordId',
snapshot: 'snapshot',
tailable: 'tailable',
tailable_cursor: 'tailable',
oplog_replay: 'oplogReplay',
no_cursor_timeout: 'noCursorTimeout',
await_data: 'awaitData',
allow_partial_results: 'allowPartialResults',
collation: 'collation'
).freeze
def_delegators :@view, :collection, :database, :filter, :options, :read
# Get the specification for an explain command that wraps the find
# command.
#
# @example Get the explain spec.
# builder.explain_specification
#
# @return [ Hash ] The specification.
#
# @since 2.2.0
def explain_specification
{ selector: { explain: find_command }, db_name: database.name, read: read, session: @session }
end
# Create the find command builder.
#
# @example Create the find command builder.
# FindCommandBuilder.new(view)
#
# @param [ Collection::View ] view The collection view.
# @param [ Session ] session The session.
#
# @since 2.2.2
def initialize(view, session)
@view = view
@session = session
end
# Get the specification to pass to the find command operation.
#
# @example Get the specification.
# builder.specification
#
# @return [ Hash ] The specification.
#
# @since 2.2.0
def specification
{ selector: find_command, db_name: database.name, read: read, session: @session }
end
private
def find_command
document = BSON::Document.new('find' => collection.name, 'filter' => filter)
document[:readConcern] = collection.read_concern if collection.read_concern
command = Options::Mapper.transform_documents(convert_flags(options), MAPPINGS, document)
convert_limit_and_batch_size(command)
command
end
def convert_limit_and_batch_size(command)
if command[:limit] && command[:limit] < 0 &&
command[:batchSize] && command[:batchSize] < 0
command[:limit] = command[:limit].abs
command[:batchSize] = command[:limit].abs
command[:singleBatch] = true
else
[:limit, :batchSize].each do |opt|
if command[opt]
if command[opt] < 0
command[opt] = command[opt].abs
command[:singleBatch] = true
elsif command[opt] == 0
command.delete(opt)
end
end
end
end
end
def convert_flags(options)
return options if options.empty?
opts = options.dup
opts.delete(:cursor_type)
Flags.map_flags(options).reduce(opts) do |o, key|
o.merge!(key => true)
end
end
end
end
end
end
end
|