Skip to content

Add a cursor for the current page. #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Sep 4, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### 2.0.0 (Next)

* [#38](https://github.com/mongoid/mongoid-scroll/pull/38): Allow to reverse the scroll - [@GCorbel](https://github.com/GCorbel).
* [#43](https://github.com/mongoid/mongoid-scroll/pull/43): Add a current cursor - [@GCorbel](https://github.com/GCorbel).
* Your contribution here.

### 1.0.1 (2023/03/15)
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ Feed::Item.desc(:position).limit(5).scroll(saved_iterator.previous_cursor) do |r
end
```

`saved_iterator.current_cursor` can be used to loop over the same records again.

The iteration finishes when no more records are available. You can also finish iterating over the remaining records by omitting the query limit.

```ruby
Expand Down
5 changes: 4 additions & 1 deletion lib/mongo/scrollable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@ def scroll(cursor_or_type = nil, options = nil, &_block)
# scroll
if block_given?
previous_cursor = nil
current_cursor = nil
records.each do |record|
previous_cursor ||= cursor_type.from_record(record, cursor_options.merge(type: :previous))
current_cursor ||= cursor_type.from_record(record, cursor_options.merge(include_current: true))
iterator = Mongoid::Criteria::Scrollable::Iterator.new(
previous_cursor: previous_cursor,
next_cursor: cursor_type.from_record(record, cursor_options)
next_cursor: cursor_type.from_record(record, cursor_options),
current_cursor: current_cursor
)
yield record, iterator
end
Expand Down
5 changes: 4 additions & 1 deletion lib/mongoid/criteria/scrollable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ def scroll(cursor_or_type = nil, &_block)
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)
next_cursor: cursor_from_record(cursor_type, record, cursor_options),
current_cursor: current_cursor
)
yield record, iterator
end
Expand Down
5 changes: 3 additions & 2 deletions lib/mongoid/criteria/scrollable/iterator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ module Mongoid
class Criteria
module Scrollable
class Iterator
attr_accessor :previous_cursor, :next_cursor
attr_accessor :previous_cursor, :current_cursor, :next_cursor

def initialize(previous_cursor:, next_cursor:)
def initialize(previous_cursor:, current_cursor:, next_cursor:)
@previous_cursor = previous_cursor
@current_cursor = current_cursor
@next_cursor = next_cursor
end
end
Expand Down
11 changes: 11 additions & 0 deletions spec/mongo/collection_view_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,17 @@
expect(Mongoid.default_client['feed_items'].find.sort(field_name => 1).limit(2).scroll(second_iterator.previous_cursor, field_type: field_type).to_a).to eq(records.limit(2).to_a)
expect(Mongoid.default_client['feed_items'].find.sort(field_name => 1).limit(2).scroll(third_iterator.previous_cursor, field_type: field_type).to_a).to eq(records.skip(2).limit(2).to_a)
end
it 'can loop over the same records with the current cursor' do
current_cursor = nil
records = Mongoid.default_client['feed_items'].find.sort(field_name => 1)
cursor = cursor_type.from_record records.skip(4).first, field_name: field_name, field_type: field_type, include_current: true

records.limit(2).scroll(cursor, field_type: field_type) do |record, iterator|
current_cursor = iterator.current_cursor
end

expect(records.limit(2).scroll(current_cursor, field_type: field_type).to_a).to eq(records.skip(4).limit(2).to_a)
end
end
end
end
Expand Down
10 changes: 10 additions & 0 deletions spec/mongoid/criteria_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,16 @@
expect(Feed::Item.asc(field_name).limit(2).scroll(second_iterator.previous_cursor)).to eq(records.limit(2))
expect(Feed::Item.asc(field_name).limit(2).scroll(third_iterator.previous_cursor)).to eq(records.skip(2).limit(2))
end
it 'can loop over the same records with the current cursor' do
current_cursor = nil
cursor = cursor_type.from_record Feed::Item.find_by(name: '7'), field_name: field_name, field_type: field_type

Feed::Item.asc(field_name).limit(2).scroll(cursor) do |_, iterator|
current_cursor = iterator.current_cursor
end

expect(Feed::Item.asc(field_name).limit(2).scroll(current_cursor).to_a).to eq(Feed::Item.asc(field_name).last(2))
end
end
end
end
Expand Down
Loading