123456789_123456789_123456789_123456789_123456789_

Module: Mongo::Collection::View::Iterable

Relationships & Source Files
Extension / Inclusion / Inheritance Descendants
Included In:
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
Defined in: lib/mongo/collection/view/iterable.rb

Overview

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

Since:

  • 2.0.0

Instance Attribute Summary

::Mongo::CursorHost - Included

#cursor

Returns the cursor associated with this view, if any.

#timeout_mode

Instance Method Summary

::Mongo::CursorHost - Included

#validate_timeout_mode!

Ensure the timeout mode is appropriate for other options that have been given.

Instance Attribute Details

#prefer_cached_cursor?Boolean (readonly, private)

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.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 189

def prefer_cached_cursor?
  use_query_cache? &&
    cached_cursor &&
    (cached_cursor.fully_iterated? || !cached_cursor.closed?)
end

#use_query_cache?Boolean (readonly, private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 181

def use_query_cache?
  QueryCache.enabled? && !collection.system_collection?
end

Instance Method Details

#cache_options (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 112

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 (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 108

def cached_cursor
  QueryCache.get(**cache_options)
end

#close_querynil Also known as: #kill_cursors

Note:

This method propagates any errors that occur when closing the server-side cursor.

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.

Returns:

  • (nil)

    Always nil.

Raises:

Since:

  • 2.1.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 75

def close_query
  if @cursor
    @cursor.close
  end
end

#compute_limit_for_cached_query (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 207

def compute_limit_for_cached_query
  return nil unless use_query_cache? && respond_to?(:limit)

  # 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.
  return QueryCache.normalized_limit(limit)
end

#each {|Each| ... } ⇒ Enumerator

Iterate through documents returned by a query with this ::Mongo::Collection::View.

Examples:

Iterate through the result of the view.

view.each do |document|
  p document
end

Yield Parameters:

  • Each (Hash)

    matching document.

Returns:

  • (Enumerator)

    The enumerator.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 43

def each
  @cursor = prefer_cached_cursor? ? cached_cursor : new_cursor_for_iteration
  return @cursor.to_enum unless block_given?

  limit_for_cached_query = compute_limit_for_cached_query

  # 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
end

#initial_query_op(session) (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 128

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],
    allow_partial_results: options[:allow_partial_results],
    read: read,
    read_concern: options[:read_concern] || read_concern,
    batch_size: batch_size,
    hint: options[:hint],
    max_scan: options[:max_scan],
    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: oplog_replay
  }

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

  maybe_set_tailable_options(spec)

  if explained?
    spec[:explain] = options[:explain]
    Operation::Explain.new(spec)
  else
    Operation::Find.new(spec)
  end
end

#kill_cursors

Alias for #close_query.

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 80

alias :kill_cursors :close_query

#maybe_set_tailable_options(spec) (private)

Add tailable cusror options to the command specifiction if needed.

Parameters:

  • spec (Hash)

    The command specification.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 219

def maybe_set_tailable_options(spec)
  case cursor_type
  when :tailable
    spec[:tailable] = true
  when :tailable_await
    spec[:tailable] = true
    spec[:await_data] = true
  end
end

#new_cursor_for_iteration (private)

Start a new cursor for use when iterating (via #each).

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 196

def new_cursor_for_iteration
  session = client.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

#oplog_replaytrue | false | nil (private)

Returns:

  • (true | false | nil)

    options, if set, otherwise the same option from the collection.

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 231

def oplog_replay
  v = options[:oplog_replay]
  v.nil? ? collection.options[:oplog_replay] : v
end

#select_cursor(session) (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 84

def select_cursor(session)
  context = Operation::Context.new(
    client: client,
    session: session,
    operation_timeouts: operation_timeouts,
    view: self
  )

  if respond_to?(:write?, true) && write?
    server = server_selector.select_server(cluster, nil, session, write_aggregation: true)
    result = send_initial_query(server, context)

    if use_query_cache?
      CachingCursor.new(view, result, server, session: session, context: context)
    else
      Cursor.new(view, result, server, session: session, context: context)
    end
  else
    read_with_retry_cursor(session, server_selector, view, context: context) do |server|
      send_initial_query(server, context)
    end
  end
end

#send_initial_query(server, context) (private)

Since:

  • 2.0.0

[ GitHub ]

  
# File 'lib/mongo/collection/view/iterable.rb', line 170

def send_initial_query(server, context)
  operation = initial_query_op(context.session)
  if server.load_balancer?
    # Connection will be checked in when cursor is drained.
    connection = server.pool.check_out(context: context)
    operation.execute_with_connection(connection, context: context)
  else
    operation.execute(server, context: context)
  end
end