Skip to content
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

Add a cursor for the current page. #43

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
Expand Up @@ -2,6 +2,7 @@

* [#38](https://github.com/mongoid/mongoid-scroll/pull/38): Add `previous_cursor` - [@GCorbel](https://github.com/GCorbel).
* [#42](https://github.com/mongoid/mongoid-scroll/pull/42): Add `first_cursor` - [@GCorbel](https://github.com/GCorbel).
* [#43](https://github.com/mongoid/mongoid-scroll/pull/43): Add `current_cursor` - [@GCorbel](https://github.com/GCorbel).
* Your contribution here.

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

Use `saved_iterator.first_cursor` to loop over the first records.
Use `saved_iterator.first_cursor` to loop over the first records or `saved_iterator.current_cursor` 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.

Expand Down Expand Up @@ -161,7 +161,7 @@ end

## Cursors

You can use `Mongoid::Scroll::Cursor.from_record` to generate a cursor. A cursor points at the last record of the previous iteration and unlike MongoDB cursors will not expire.
You can use `Mongoid::Scroll::Cursor.from_record` to generate a cursor. A cursor points at the last record of the iteration and unlike MongoDB cursors will not expire.

```ruby
record = Feed::Item.desc(:position).limit(3).last
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))
dblock marked this conversation as resolved.
Show resolved Hide resolved
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

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
it 'can loop over the first records with the first cursor' do
first_cursor = nil
records = Mongoid.default_client['feed_items'].find.sort(field_name => 1)
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.skip(4).first, field_name: field_name, field_type: field_type, include_current: true

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).skip(4).limit(2).to_a)
end
it 'can loop over the first records with the first page cursor' do
first_cursor = nil

Expand Down
Loading