mongoid-scroll 0.3.2 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +0 -2
- data/.rubocop_todo.yml +38 -17
- data/.travis.yml +31 -12
- data/CHANGELOG.md +32 -16
- data/Dangerfile +1 -0
- data/Gemfile +13 -10
- data/LICENSE.md +1 -1
- data/README.md +31 -11
- data/RELEASING.md +67 -0
- data/Rakefile +1 -1
- data/examples/mongo_ruby_driver_scroll_feed.rb +45 -0
- data/examples/mongoid_scroll_feed.rb +8 -3
- data/examples/moped_scroll_feed.rb +2 -0
- data/lib/config/locales/en.yml +1 -1
- data/lib/mongo/scrollable.rb +34 -0
- data/lib/mongoid-scroll.rb +3 -6
- data/lib/mongoid/criteria/scrollable.rb +81 -0
- data/lib/mongoid/scroll/cursor.rb +15 -11
- data/lib/mongoid/scroll/errors/base.rb +1 -1
- data/lib/mongoid/scroll/version.rb +1 -1
- data/lib/moped/scrollable.rb +7 -6
- data/mongoid-scroll.gemspec +2 -1
- data/spec/mongo/collection_view_spec.rb +126 -0
- data/spec/mongoid/criteria_spec.rb +39 -4
- data/spec/mongoid/scroll_cursor_spec.rb +25 -25
- data/spec/moped/query_spec.rb +100 -98
- data/spec/spec_helper.rb +6 -1
- data/spec/support/feed/item.rb +5 -1
- data/spec/support/feed/publisher.rb +9 -0
- data/spec/support/mongodb.rb +9 -0
- metadata +30 -11
- data/lib/mongoid/criterion/scrollable.rb +0 -33
- data/lib/mongoid/scroll/mongoid.rb +0 -7
@@ -4,6 +4,14 @@ Bundler.setup(:default, :development)
|
|
4
4
|
require 'mongoid-scroll'
|
5
5
|
require 'faker'
|
6
6
|
|
7
|
+
if defined?(Moped)
|
8
|
+
Moped.logger = Logger.new($stdout)
|
9
|
+
Moped.logger.level = Logger::DEBUG
|
10
|
+
else
|
11
|
+
Mongoid.logger.level = Logger::INFO
|
12
|
+
Mongo::Logger.logger.level = Logger::INFO if Mongoid::Compatibility::Version.mongoid5?
|
13
|
+
end
|
14
|
+
|
7
15
|
Mongoid.connect_to 'mongoid_scroll_demo'
|
8
16
|
Mongoid.purge!
|
9
17
|
|
@@ -27,9 +35,6 @@ total_items.times do |_i|
|
|
27
35
|
Feed::Item.create! title: Faker::Lorem.sentence, position: rands.pop
|
28
36
|
end
|
29
37
|
|
30
|
-
Moped.logger = Logger.new($stdout)
|
31
|
-
Moped.logger.level = Logger::DEBUG
|
32
|
-
|
33
38
|
Feed::Item.create_indexes
|
34
39
|
|
35
40
|
total_shown = 0
|
data/lib/config/locales/en.yml
CHANGED
@@ -18,5 +18,5 @@ en:
|
|
18
18
|
unsupported_field_type:
|
19
19
|
message: "Unsupported field type."
|
20
20
|
summary: "The type of the field '%{field}' is not supported: %{type}."
|
21
|
-
resolution: "Please open a feature request in https://github.com/
|
21
|
+
resolution: "Please open a feature request in https://github.com/mongoid/mongoid-scroll."
|
22
22
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Mongo
|
2
|
+
module Scrollable
|
3
|
+
def scroll(cursor = nil, options = nil, &_block)
|
4
|
+
view = self
|
5
|
+
# we don't support scrolling over a view with multiple fields
|
6
|
+
raise Mongoid::Scroll::Errors::MultipleSortFieldsError.new(sort: view.sort) if view.sort && view.sort.keys.size != 1
|
7
|
+
# scroll field and direction
|
8
|
+
scroll_field = view.sort ? view.sort.keys.first : :_id
|
9
|
+
scroll_direction = view.sort ? view.sort.values.first.to_i : 1
|
10
|
+
# scroll cursor from the parameter, with value and tiebreak_id
|
11
|
+
options = { field_type: BSON::ObjectId } unless options
|
12
|
+
cursor_options = { field_name: scroll_field, direction: scroll_direction }.merge(options)
|
13
|
+
cursor = cursor.is_a?(Mongoid::Scroll::Cursor) ? cursor : Mongoid::Scroll::Cursor.new(cursor, cursor_options)
|
14
|
+
# make a view
|
15
|
+
view = Mongo::Collection::View.new(
|
16
|
+
view.collection,
|
17
|
+
view.selector.merge(cursor.criteria),
|
18
|
+
sort: (view.sort || {}).merge(_id: scroll_direction),
|
19
|
+
skip: skip,
|
20
|
+
limit: limit
|
21
|
+
)
|
22
|
+
# scroll
|
23
|
+
if block_given?
|
24
|
+
view.each do |record|
|
25
|
+
yield record, Mongoid::Scroll::Cursor.from_record(record, cursor_options)
|
26
|
+
end
|
27
|
+
else
|
28
|
+
view
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Mongo::Collection::View.send(:include, Mongo::Scrollable)
|
data/lib/mongoid-scroll.rb
CHANGED
@@ -3,13 +3,10 @@ require 'i18n'
|
|
3
3
|
I18n.load_path << File.join(File.dirname(__FILE__), 'config', 'locales', 'en.yml')
|
4
4
|
|
5
5
|
require 'mongoid'
|
6
|
+
require 'mongoid-compatibility'
|
6
7
|
require 'mongoid/scroll/version'
|
7
|
-
require 'mongoid/scroll/mongoid'
|
8
8
|
require 'mongoid/scroll/errors'
|
9
9
|
require 'mongoid/scroll/cursor'
|
10
|
-
|
11
10
|
require 'moped/scrollable' if Object.const_defined?(:Moped)
|
12
|
-
require '
|
13
|
-
|
14
|
-
Moped::Query.send(:include, Moped::Scrollable) if Object.const_defined?(:Moped)
|
15
|
-
Mongoid::Criteria.send(:include, Mongoid::Criterion::Scrollable)
|
11
|
+
require 'mongo/scrollable' if Object.const_defined?(:Mongo)
|
12
|
+
require 'mongoid/criteria/scrollable'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Mongoid
|
2
|
+
class Criteria
|
3
|
+
module Scrollable
|
4
|
+
def scroll(cursor = nil, &_block)
|
5
|
+
raise_multiple_sort_fields_error if multiple_sort_fields?
|
6
|
+
criteria = dup
|
7
|
+
criteria.merge!(default_sort) if no_sort_option?
|
8
|
+
cursor_options = build_cursor_options(criteria)
|
9
|
+
cursor = cursor.is_a?(Mongoid::Scroll::Cursor) ? cursor : new_cursor(cursor, cursor_options)
|
10
|
+
cursor_criteria = build_cursor_criteria(criteria, cursor)
|
11
|
+
if block_given?
|
12
|
+
cursor_criteria.order_by(_id: scroll_direction(criteria)).each do |record|
|
13
|
+
yield record, cursor_from_record(record, cursor_options)
|
14
|
+
end
|
15
|
+
else
|
16
|
+
cursor_criteria
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def raise_multiple_sort_fields_error
|
23
|
+
raise Mongoid::Scroll::Errors::MultipleSortFieldsError.new(sort: criteria.options.sort)
|
24
|
+
end
|
25
|
+
|
26
|
+
def multiple_sort_fields?
|
27
|
+
options.sort && options.sort.keys.size != 1
|
28
|
+
end
|
29
|
+
|
30
|
+
def no_sort_option?
|
31
|
+
options.sort.blank? || options.sort.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
def default_sort
|
35
|
+
asc(:_id)
|
36
|
+
end
|
37
|
+
|
38
|
+
def scroll_field(criteria)
|
39
|
+
criteria.options.sort.keys.first
|
40
|
+
end
|
41
|
+
|
42
|
+
def scroll_direction(criteria)
|
43
|
+
criteria.options.sort.values.first.to_i
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_cursor_options(criteria)
|
47
|
+
{
|
48
|
+
field_type: scroll_field_type(criteria),
|
49
|
+
field_name: scroll_field(criteria),
|
50
|
+
direction: scroll_direction(criteria)
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def new_cursor(cursor, cursor_options)
|
55
|
+
Mongoid::Scroll::Cursor.new(cursor, cursor_options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def build_cursor_criteria(criteria, cursor)
|
59
|
+
cursor_criteria = criteria.dup
|
60
|
+
cursor_criteria.selector = { '$and' => [criteria.selector, cursor.criteria] }
|
61
|
+
cursor_criteria
|
62
|
+
end
|
63
|
+
|
64
|
+
def cursor_from_record(record, cursor_options)
|
65
|
+
Mongoid::Scroll::Cursor.from_record(record, cursor_options)
|
66
|
+
end
|
67
|
+
|
68
|
+
def scroll_field_type(criteria)
|
69
|
+
scroll_field = scroll_field(criteria)
|
70
|
+
field = criteria.klass.fields[scroll_field.to_s]
|
71
|
+
field.foreign_key? && field.object_id_field? ? bson_type : field.type
|
72
|
+
end
|
73
|
+
|
74
|
+
def bson_type
|
75
|
+
Mongoid::Compatibility::Version.mongoid3? ? Moped::BSON::ObjectId : BSON::ObjectId
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
Mongoid::Criteria.send(:include, Mongoid::Criteria::Scrollable)
|
@@ -14,8 +14,12 @@ module Mongoid
|
|
14
14
|
compare_direction = direction == 1 ? '$gt' : '$lt'
|
15
15
|
cursor_criteria = { field_name => { compare_direction => mongo_value } } if mongo_value
|
16
16
|
tiebreak_criteria = { field_name => mongo_value, :_id => { compare_direction => tiebreak_id } } if mongo_value && tiebreak_id
|
17
|
-
cursor_selector =
|
18
|
-
|
17
|
+
cursor_selector = if Mongoid::Compatibility::Version.mongoid6? || Mongoid::Compatibility::Version.mongoid7?
|
18
|
+
Mongoid::Criteria::Queryable::Selector.new
|
19
|
+
else
|
20
|
+
Origin::Selector.new
|
21
|
+
end
|
22
|
+
cursor_selector['$or'] = [cursor_criteria, tiebreak_criteria].compact if cursor_criteria || tiebreak_criteria
|
19
23
|
cursor_selector.__evolve_object_id__
|
20
24
|
end
|
21
25
|
|
@@ -39,16 +43,16 @@ module Mongoid
|
|
39
43
|
return unless value
|
40
44
|
parts = value.split(':')
|
41
45
|
unless parts.length >= 2
|
42
|
-
|
46
|
+
raise Mongoid::Scroll::Errors::InvalidCursorError.new(cursor: value)
|
43
47
|
end
|
44
48
|
id = parts[-1]
|
45
49
|
value = parts[0...-1].join(':')
|
46
50
|
@value = Mongoid::Scroll::Cursor.parse_field_value(field_type, field_name, value)
|
47
|
-
if Mongoid::
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
51
|
+
@tiebreak_id = if Mongoid::Compatibility::Version.mongoid3?
|
52
|
+
Moped::BSON::ObjectId(id)
|
53
|
+
else
|
54
|
+
BSON::ObjectId.from_string(id)
|
55
|
+
end
|
52
56
|
end
|
53
57
|
|
54
58
|
class << self
|
@@ -58,7 +62,7 @@ module Mongoid
|
|
58
62
|
elsif options && (field = options[:field])
|
59
63
|
[field.type.to_s, field.name.to_s]
|
60
64
|
else
|
61
|
-
|
65
|
+
raise ArgumentError.new 'Missing options[:field_name] and/or options[:field_type].'
|
62
66
|
end
|
63
67
|
end
|
64
68
|
|
@@ -72,7 +76,7 @@ module Mongoid
|
|
72
76
|
when 'Float' then value.to_f
|
73
77
|
when 'Integer' then value.to_i
|
74
78
|
else
|
75
|
-
|
79
|
+
raise Mongoid::Scroll::Errors::UnsupportedFieldTypeError.new(field: field_name, type: field_type)
|
76
80
|
end
|
77
81
|
end
|
78
82
|
|
@@ -85,7 +89,7 @@ module Mongoid
|
|
85
89
|
when 'Float' then value.to_f
|
86
90
|
when 'Integer' then value.to_i
|
87
91
|
else
|
88
|
-
|
92
|
+
raise Mongoid::Scroll::Errors::UnsupportedFieldTypeError.new(field: field_name, type: field_type)
|
89
93
|
end
|
90
94
|
end
|
91
95
|
end
|
data/lib/moped/scrollable.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
module Moped
|
2
2
|
module Scrollable
|
3
3
|
def scroll(cursor = nil, options = nil, &_block)
|
4
|
-
options
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end unless options
|
4
|
+
unless options
|
5
|
+
bson_type = Mongoid::Compatibility::Version.mongoid3? ? Moped::BSON::ObjectId : BSON::ObjectId
|
6
|
+
options = { field_type: bson_type }
|
7
|
+
end
|
9
8
|
query = Query.new(collection, operation.selector.dup)
|
10
9
|
query.operation.skip = operation.skip
|
11
10
|
query.operation.limit = operation.limit
|
12
11
|
# we don't support scrolling over a criteria with multiple fields
|
13
12
|
if query.operation.selector['$orderby'] && query.operation.selector['$orderby'].keys.size != 1
|
14
|
-
|
13
|
+
raise Mongoid::Scroll::Errors::MultipleSortFieldsError.new(sort: query.operation.selector['$orderby'])
|
15
14
|
elsif !query.operation.selector.key?('$orderby') || query.operation.selector['$orderby'].empty?
|
16
15
|
# introduce a default sort order if there's none
|
17
16
|
query.sort(_id: 1)
|
@@ -35,3 +34,5 @@ module Moped
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
37
|
+
|
38
|
+
Moped::Query.send(:include, Moped::Scrollable)
|
data/mongoid-scroll.gemspec
CHANGED
@@ -10,9 +10,10 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.required_rubygems_version = '>= 1.3.6'
|
11
11
|
s.files = `git ls-files`.split("\n")
|
12
12
|
s.require_paths = ['lib']
|
13
|
-
s.homepage = 'http://github.com/
|
13
|
+
s.homepage = 'http://github.com/mongoid/mongoid-scroll'
|
14
14
|
s.licenses = ['MIT']
|
15
15
|
s.summary = 'Mongoid extensions to enable infinite scroll.'
|
16
16
|
s.add_dependency 'mongoid', '>= 3.0'
|
17
|
+
s.add_dependency 'mongoid-compatibility'
|
17
18
|
s.add_dependency 'i18n'
|
18
19
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
if Object.const_defined?(:Mongo)
|
4
|
+
describe Mongo::Collection::View do
|
5
|
+
context 'scrollable' do
|
6
|
+
subject do
|
7
|
+
Mongoid.default_client['feed_items'].find
|
8
|
+
end
|
9
|
+
it ':scroll' do
|
10
|
+
expect(subject).to respond_to(:scroll)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
context 'with multiple sort fields' do
|
14
|
+
subject do
|
15
|
+
Mongoid.default_client['feed_items'].find.sort(name: 1, value: -1)
|
16
|
+
end
|
17
|
+
it 'raises Mongoid::Scroll::Errors::MultipleSortFieldsError' do
|
18
|
+
expect { subject.scroll }.to raise_error Mongoid::Scroll::Errors::MultipleSortFieldsError,
|
19
|
+
/You're attempting to scroll over data with a sort order that includes multiple fields: name, value./
|
20
|
+
end
|
21
|
+
end
|
22
|
+
context 'with no sort' do
|
23
|
+
subject do
|
24
|
+
Mongoid.default_client['feed_items'].find
|
25
|
+
end
|
26
|
+
it 'adds a default sort by _id' do
|
27
|
+
expect(subject.scroll.sort).to eq('_id' => 1)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
context 'with data' do
|
31
|
+
before :each do
|
32
|
+
10.times do |i|
|
33
|
+
Mongoid.default_client['feed_items'].insert_one(
|
34
|
+
a_string: i.to_s,
|
35
|
+
a_integer: i,
|
36
|
+
a_datetime: DateTime.mongoize(DateTime.new(2013, i + 1, 21, 1, 42, 3, 'UTC')),
|
37
|
+
a_date: Date.mongoize(Date.new(2013, i + 1, 21)),
|
38
|
+
a_time: Time.mongoize(Time.at(Time.now.to_i + i))
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
context 'default' do
|
43
|
+
it 'scrolls all' do
|
44
|
+
records = []
|
45
|
+
Mongoid.default_client['feed_items'].find.scroll do |record, _next_cursor|
|
46
|
+
records << record
|
47
|
+
end
|
48
|
+
expect(records.size).to eq 10
|
49
|
+
expect(records).to eq Mongoid.default_client['feed_items'].find.to_a
|
50
|
+
end
|
51
|
+
end
|
52
|
+
{ a_string: String, a_integer: Integer, a_date: Date, a_datetime: DateTime }.each_pair do |field_name, field_type|
|
53
|
+
context field_type do
|
54
|
+
it 'scrolls all with a block' do
|
55
|
+
records = []
|
56
|
+
Mongoid.default_client['feed_items'].find.sort(field_name => 1).scroll(nil, field_type: field_type) do |record, _next_cursor|
|
57
|
+
records << record
|
58
|
+
end
|
59
|
+
expect(records.size).to eq 10
|
60
|
+
expect(records).to eq Mongoid.default_client['feed_items'].find.to_a
|
61
|
+
end
|
62
|
+
it 'scrolls all with a break' do
|
63
|
+
records = []
|
64
|
+
cursor = nil
|
65
|
+
Mongoid.default_client['feed_items'].find.sort(field_name => 1).limit(5).scroll(nil, field_type: field_type) do |record, next_cursor|
|
66
|
+
records << record
|
67
|
+
cursor = next_cursor
|
68
|
+
end
|
69
|
+
expect(records.size).to eq 5
|
70
|
+
Mongoid.default_client['feed_items'].find.sort(field_name => 1).scroll(cursor, field_type: field_type) do |record, next_cursor|
|
71
|
+
records << record
|
72
|
+
cursor = next_cursor
|
73
|
+
end
|
74
|
+
expect(records.size).to eq 10
|
75
|
+
expect(records).to eq Mongoid.default_client['feed_items'].find.to_a
|
76
|
+
end
|
77
|
+
it 'scrolls in descending order' do
|
78
|
+
records = []
|
79
|
+
Mongoid.default_client['feed_items'].find.sort(field_name => -1).limit(3).scroll(nil, field_type: field_type, field_name: field_name) do |record, _next_cursor|
|
80
|
+
records << record
|
81
|
+
end
|
82
|
+
expect(records.size).to eq 3
|
83
|
+
expect(records).to eq Mongoid.default_client['feed_items'].find.sort(field_name => -1).limit(3).to_a
|
84
|
+
end
|
85
|
+
it 'map' do
|
86
|
+
record = Mongoid.default_client['feed_items'].find.limit(3).scroll(nil, field_type: field_type, field_name: field_name).map { |r| r }.last
|
87
|
+
cursor = Mongoid::Scroll::Cursor.from_record(record, field_type: field_type, field_name: field_name)
|
88
|
+
expect(cursor).to_not be nil
|
89
|
+
expect(cursor.to_s.split(':')).to eq [
|
90
|
+
Mongoid::Scroll::Cursor.transform_field_value(field_type, field_name, record[field_name.to_s]).to_s,
|
91
|
+
record['_id'].to_s
|
92
|
+
]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
context 'with overlapping data', if: MongoDB.mmapv1? do
|
98
|
+
before :each do
|
99
|
+
3.times { Feed::Item.create! a_integer: 5 }
|
100
|
+
Feed::Item.first.update_attributes!(name: Array(1000).join('a'))
|
101
|
+
end
|
102
|
+
it 'natural order is different from order by id' do
|
103
|
+
# natural order isn't necessarily going to be the same as _id order
|
104
|
+
# if a document is updated and grows in size, it may need to be relocated and
|
105
|
+
# thus cause the natural order to change
|
106
|
+
expect(Feed::Item.order_by('$natural' => 1).to_a).to_not eq Feed::Item.order_by(_id: 1).to_a
|
107
|
+
end
|
108
|
+
[{ a_integer: 1 }, { a_integer: -1 }].each do |sort_order|
|
109
|
+
it "scrolls by #{sort_order}" do
|
110
|
+
records = []
|
111
|
+
cursor = nil
|
112
|
+
Mongoid.default_client['feed_items'].find.sort(sort_order).limit(2).scroll do |record, next_cursor|
|
113
|
+
records << record
|
114
|
+
cursor = next_cursor
|
115
|
+
end
|
116
|
+
expect(records.size).to eq 2
|
117
|
+
Mongoid.default_client['feed_items'].find.sort(sort_order).scroll(cursor) do |record, _next_cursor|
|
118
|
+
records << record
|
119
|
+
end
|
120
|
+
expect(records.size).to eq 3
|
121
|
+
expect(records).to eq Mongoid.default_client['feed_items'].find.sort(sort_order.merge(_id: sort_order[:a_integer])).to_a
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -13,6 +13,7 @@ describe Mongoid::Criteria do
|
|
13
13
|
/You're attempting to scroll over data with a sort order that includes multiple fields: name, value./
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
16
17
|
context 'with no sort' do
|
17
18
|
subject do
|
18
19
|
Feed::Item.all
|
@@ -42,7 +43,30 @@ describe Mongoid::Criteria do
|
|
42
43
|
expect(records.size).to eq 10
|
43
44
|
expect(records).to eq Feed::Item.all.to_a
|
44
45
|
end
|
46
|
+
it 'does not change original criteria' do
|
47
|
+
criteria = Feed::Item.where(:a_time.gt => Time.new(2013, 7, 22, 1, 2, 3))
|
48
|
+
original_criteria = criteria.dup
|
49
|
+
criteria.limit(2).scroll
|
50
|
+
expect(criteria).to eq original_criteria
|
51
|
+
cursor = nil
|
52
|
+
criteria.limit(2).scroll(cursor) do |_record, next_cursor|
|
53
|
+
cursor = next_cursor
|
54
|
+
end
|
55
|
+
criteria.scroll(cursor) do |_record, next_cursor|
|
56
|
+
cursor = next_cursor
|
57
|
+
end
|
58
|
+
expect(criteria).to eq original_criteria
|
59
|
+
end
|
45
60
|
end
|
61
|
+
|
62
|
+
context 'with a foreign key' do
|
63
|
+
it 'sorts by object id' do
|
64
|
+
records = []
|
65
|
+
Feed::Item.asc('publisher_id').scroll { |r, _| records << r }
|
66
|
+
expect(records).not_to be_empty
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
46
70
|
{ a_string: String, a_integer: Integer, a_date: Date, a_datetime: DateTime }.each_pair do |field_name, field_type|
|
47
71
|
context field_type do
|
48
72
|
it 'scrolls all with a block' do
|
@@ -68,6 +92,17 @@ describe Mongoid::Criteria do
|
|
68
92
|
expect(records.size).to eq 10
|
69
93
|
expect(records).to eq Feed::Item.all.to_a
|
70
94
|
end
|
95
|
+
it 'scrolls from a cursor' do
|
96
|
+
last_record = nil
|
97
|
+
cursor = nil
|
98
|
+
Feed::Item.asc(field_name).limit(5).scroll do |record, next_cursor|
|
99
|
+
last_record = record
|
100
|
+
cursor = next_cursor
|
101
|
+
end
|
102
|
+
sixth_item = Feed::Item.asc(field_name).to_a[5]
|
103
|
+
from_item = Feed::Item.asc(field_name).scroll(cursor).to_a.first
|
104
|
+
expect(from_item).to eq sixth_item
|
105
|
+
end
|
71
106
|
it 'scrolls in descending order' do
|
72
107
|
records = []
|
73
108
|
Feed::Item.desc(field_name).limit(3).scroll do |record, _next_cursor|
|
@@ -132,9 +167,9 @@ describe Mongoid::Criteria do
|
|
132
167
|
end
|
133
168
|
it 'merges cursor criteria when no sort field is given' do
|
134
169
|
criteria = Feed::Item.where(:a_time.gt => Time.new(2013, 7, 22, 1, 2, 3))
|
135
|
-
|
136
|
-
cursor_input = "#{
|
137
|
-
field_type = Mongoid::
|
170
|
+
feed_item = Feed::Item.where(name: 'Feed Item 1').first
|
171
|
+
cursor_input = "#{feed_item.id}:#{feed_item.id}"
|
172
|
+
field_type = Mongoid::Compatibility::Version.mongoid3? ? Moped::BSON::ObjectId : BSON::ObjectId
|
138
173
|
cursor_options = { field_type: field_type, field_name: '_id', direction: 1 }
|
139
174
|
cursor = Mongoid::Scroll::Cursor.new(cursor_input, cursor_options)
|
140
175
|
records = []
|
@@ -160,7 +195,7 @@ describe Mongoid::Criteria do
|
|
160
195
|
expect(records.map(&:name)).to eq ['embedded']
|
161
196
|
end
|
162
197
|
end
|
163
|
-
context 'with overlapping data' do
|
198
|
+
context 'with overlapping data', if: MongoDB.mmapv1? do
|
164
199
|
before :each do
|
165
200
|
3.times { Feed::Item.create! a_integer: 5 }
|
166
201
|
Feed::Item.first.update_attributes!(name: Array(1000).join('a'))
|