module Mongo::Collection::View::Iterable

Defines iteration related behavior for collection views, including cursor instantiation.

@since 2.0.0

Attributes

cursor[R]

Returns the cursor associated with this view, if any.

@return [ nil | Cursor ] The cursor, if any.

@api private

Public Instance Methods

close_query() click to toggle source

Cleans up resources associated with this query.

If there is a server cursor associated with this query, it is closed by sending a KillCursors command to the server.

@note This method propagates any errors that occur when closing the

server-side cursor.

@return [ nil ] Always nil.

@raise [ Error::OperationFailure ] If the server cursor close fails.

@since 2.1.0

# File lib/mongo/collection/view/iterable.rb, line 105
def close_query
  if @cursor
    @cursor.close
  end
end
Also aliased as: kill_cursors
each() { |doc| ... } click to toggle source

Iterate through documents returned by a query with this View.

@example Iterate through the result of the view.

view.each do |document|
  p document
end

@return [ Enumerator ] The enumerator.

@since 2.0.0

@yieldparam [ Hash ] Each matching document.

# File lib/mongo/collection/view/iterable.rb, line 46
def each
  # If the caching cursor is closed and was not fully iterated,
  # the documents we have in it are not the complete result set and
  # we have no way of completing that iteration.
  # Therefore, discard that cursor and start iteration again.
  # The case of the caching cursor not being closed and not having
  # been fully iterated isn't tested - see RUBY-2773.
  @cursor = if use_query_cache? && cached_cursor && (
    cached_cursor.fully_iterated? || !cached_cursor.closed?
  )
    cached_cursor
  else
    session = client.send(:get_session, @options)
    select_cursor(session).tap do |cursor|
      if use_query_cache?
        # No need to store the cursor in the query cache if there is
        # already a cached cursor stored at this key.
        QueryCache.set(cursor, **cache_options)
      end
    end
  end

  if use_query_cache?
    # If a query with a limit is performed, the query cache will
    # re-use results from an earlier query with the same or larger
    # limit, and then impose the lower limit during iteration.
    limit_for_cached_query = respond_to?(:limit) ? QueryCache.normalized_limit(limit) : nil
  end

  if block_given?
    # Ruby versions 2.5 and older do not support arr[0..nil] syntax, so
    # this must be a separate conditional.
    cursor_to_iterate = if limit_for_cached_query
      @cursor.to_a[0...limit_for_cached_query]
    else
      @cursor
    end

    cursor_to_iterate.each do |doc|
      yield doc
    end
  else
    @cursor.to_enum
  end
end
kill_cursors()
Alias for: close_query

Private Instance Methods

cache_options() click to toggle source
# File lib/mongo/collection/view/iterable.rb, line 135
def cache_options
  # NB: this hash is passed as keyword argument and must have symbol
  # keys.
  {
    namespace: collection.namespace,
    selector: selector,
    skip: skip,
    sort: sort,
    limit: limit,
    projection: projection,
    collation: collation,
    read_concern: read_concern,
    read_preference: read_preference,
  }
end
cached_cursor() click to toggle source
# File lib/mongo/collection/view/iterable.rb, line 131
def cached_cursor
  QueryCache.get(**cache_options)
end
initial_query_op(session) click to toggle source
# File lib/mongo/collection/view/iterable.rb, line 151
def initial_query_op(session)
  spec = {
    coll_name: collection.name,
    filter: filter,
    projection: projection,
    db_name: database.name,
    session: session,
    collation: collation,
    sort: sort,
    skip: skip,
    let: options[:let],
    limit: limit,
    allow_disk_use: options[:allow_disk_use],
    read: read,
    read_concern: options[:read_concern] || read_concern,
    batch_size: batch_size,
    hint: options[:hint],
    max_scan: options[:max_scan],
    max_time_ms: options[:max_time_ms],
    max_value: options[:max_value],
    min_value: options[:min_value],
    no_cursor_timeout: options[:no_cursor_timeout],
    return_key: options[:return_key],
    show_disk_loc: options[:show_disk_loc],
    comment: options[:comment],
    oplog_replay: if (v = options[:oplog_replay]).nil?
      collection.options[:oplog_replay]
    else
      v
    end,
  }

  if spec[:oplog_replay]
    collection.client.log_warn("The :oplog_replay option is deprecated and ignored by MongoDB 4.4 and later")
  end

  if explained?
    spec[:explain] = options[:explain]
    Operation::Explain.new(spec)
  else
    Operation::Find.new(spec)
  end
end
select_cursor(session) click to toggle source
# File lib/mongo/collection/view/iterable.rb, line 114
def select_cursor(session)
  if respond_to?(:write?, true) && write?
    server = server_selector.select_server(cluster, nil, session, write_aggregation: true)
    result = send_initial_query(server, session)

    if use_query_cache?
      CachingCursor.new(view, result, server, session: session)
    else
      Cursor.new(view, result, server, session: session)
    end
  else
    read_with_retry_cursor(session, server_selector, view) do |server|
      send_initial_query(server, session)
    end
  end
end
send_initial_query(server, session = nil) click to toggle source
# File lib/mongo/collection/view/iterable.rb, line 195
def send_initial_query(server, session = nil)
  initial_query_op(session).execute(server, context: Operation::Context.new(client: client, session: session))
end
use_query_cache?() click to toggle source
# File lib/mongo/collection/view/iterable.rb, line 199
def use_query_cache?
  QueryCache.enabled? && !collection.system_collection?
end