module Mongoid::Criteria::Scrollable

Public Instance Methods

scroll(cursor_or_type = nil) { |record, iterator| ... } click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 7
def scroll(cursor_or_type = nil, &_block)
  cursor, cursor_type = cursor_and_type(cursor_or_type)
  raise_multiple_sort_fields_error if multiple_sort_fields?
  criteria = dup
  criteria.merge!(default_sort) if no_sort_option?
  cursor_options = build_cursor_options(criteria)
  cursor = new_cursor(cursor_type, cursor, cursor_options) unless cursor.is_a?(cursor_type)
  raise_mismatched_sort_fields_error!(cursor, cursor_options) if different_sort_fields?(cursor, cursor_options)
  records = find_records(criteria, cursor)
  if block_given?
    previous_cursor = nil
    current_cursor = nil
    records.each do |record|
      previous_cursor ||= cursor_from_record(cursor_type, record, cursor_options.merge(type: :previous))
      current_cursor ||= cursor_from_record(cursor_type, record, cursor_options.merge(include_current: true))
      iterator = Mongoid::Criteria::Scrollable::Iterator.new(
        previous_cursor: previous_cursor,
        next_cursor: cursor_from_record(cursor_type, record, cursor_options),
        current_cursor: current_cursor
      )
      yield record, iterator
    end
  else
    records
  end
end

Private Instance Methods

build_cursor_options(criteria) click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 60
def build_cursor_options(criteria)
  {
    field_type: scroll_field_type(criteria),
    field_name: scroll_field(criteria),
    direction: scroll_direction(criteria)
  }
end
cursor_from_record(cursor_type, record, cursor_options) click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 89
def cursor_from_record(cursor_type, record, cursor_options)
  cursor_type.from_record(record, cursor_options)
end
default_sort() click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 48
def default_sort
  asc(:_id)
end
find_records(criteria, cursor) click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 72
def find_records(criteria, cursor)
  cursor_criteria = criteria.dup
  cursor_criteria.selector = { '$and' => [criteria.selector, cursor.criteria] }
  if cursor.type == :previous
    pipeline = [
      { '$match' => cursor_criteria.selector },
      { '$sort' => { cursor.field_name => -cursor.direction } },
      { '$limit' => criteria.options[:limit] },
      { '$sort' => { cursor.field_name => cursor.direction } }
    ]
    aggregation = cursor_criteria.view.aggregate(pipeline)
    aggregation.map { |record| Mongoid::Factory.from_db(cursor_criteria.klass, record) }
  else
    cursor_criteria.order_by(_id: scroll_direction(criteria))
  end
end
multiple_sort_fields?() click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 40
def multiple_sort_fields?
  options.sort && options.sort.keys.size != 1
end
new_cursor(cursor_type, cursor, cursor_options) click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 68
def new_cursor(cursor_type, cursor, cursor_options)
  cursor_type.new(cursor, cursor_options)
end
no_sort_option?() click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 44
def no_sort_option?
  options.sort.blank? || options.sort.empty?
end
raise_multiple_sort_fields_error() click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 36
def raise_multiple_sort_fields_error
  raise Mongoid::Scroll::Errors::MultipleSortFieldsError.new(sort: criteria.options.sort)
end
scroll_direction(criteria) click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 56
def scroll_direction(criteria)
  criteria.options.sort.values.first.to_i
end
scroll_field(criteria) click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 52
def scroll_field(criteria)
  criteria.options.sort.keys.first
end
scroll_field_type(criteria) click to toggle source
# File lib/mongoid/criteria/scrollable.rb, line 93
def scroll_field_type(criteria)
  scroll_field = scroll_field(criteria)
  field = criteria.klass.fields[scroll_field.to_s]
  field.foreign_key? && field.object_id_field? ? BSON::ObjectId : field.type
end