Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

sorting is more performant now

  • Loading branch information...
commit d8804eb78dcf6097457018205c28a77f6413babf 1 parent 270a5fe
@mharris717 authored
View
18 lib/mongo_delegate/composite_cursor.rb
@@ -36,9 +36,20 @@ class FindOps
def options; cursor.options; end
fattr(:num_using) { res.map { |x| x[0].to_af.size }.sum }
fattr(:found_ids) { res.map { |x| x[1].to_af.map { |x| x['_id'] } }.flatten }
+ fattr(:limit) do
+ if options[:limit]
+ if options[:sort]
+ options[:limit]
+ else
+ options[:limit] - num_using
+ end
+ else
+ nil
+ end
+ end
fattr(:ops) do
r = {}
- r[:limit] = (options[:limit] - num_using) if options[:limit] && !options[:sort]
+ r[:limit] = limit if limit
r[:skip] = [(options[:skip] - found_ids.size ),0].max if options[:skip] && !options[:sort]
r[:sort] = options[:sort] if options[:sort]
r
@@ -59,8 +70,11 @@ def sort_proc
foc.map { |k,v| (v == 1) ? doc[k] : doc[k].sortflip }
end
end
+ fattr(:raw_rows) do
+ cursors.map { |x| x.to_af }.flatten
+ end
fattr(:rows) do
- res = cursors.map { |x| x.to_af }.flatten
+ res = raw_rows
res = res.sort_by(&sort_proc) if sort_proc
res = res[0...(options[:limit])] if options[:limit]
res = res[(options[:skip])..-1] if options[:skip] && options[:sort]
View
61 spec/delegating_collection_spec.rb
@@ -2,12 +2,13 @@
context Mongo::DelegatingCollection do
def setup_coll
+ @start_time = Time.now
@conn = Mongo::Connection.new
@db = Mongo::DelegatingDatabase.new(:remote => @conn.db('dc-remote'), :local => @conn.db('dc-local'))
@d = @db.collection('abc')
@d.remove
- @remotes = %w(Ellen Randy Barbara).each { |x| @d.remote.save(:name => x) }
- @locals = %w(Mike Lou Lowell).each { |x| @d.local.save(:name => x) }
+ @remotes = %w(Barbara Danny Frank).each { |x| @d.remote.save(:name => x) }
+ @locals = %w(Adam Chris Eric).each { |x| @d.local.save(:name => x) }
@all = @remotes + @locals
end
context 'find' do
@@ -16,7 +17,7 @@ def setup_coll
@d.find.count.should == @all.size
end
it 'find doesnt return dups' do
- @d.save(@d.remote.find_one(:name => 'Randy'))
+ @d.save(@d.remote.find_one(:name => @remotes.first))
@d.find.count.should == @all.size
@d.find.unpruned_rows.size.should == @all.size + 1
end
@@ -26,9 +27,9 @@ def setup_coll
@d.find.rows
end
it 'find returns local precedence' do
- r = @d.remote.find_one(:name => 'Randy').merge(:age => 'old')
+ r = @d.remote.find_one(:name => @remotes.first).merge(:age => 'old')
@d.local.save(r)
- @d.find_one(:name => 'Randy')['age'].should == 'old'
+ @d.find_one(:name => @remotes.first)['age'].should == 'old'
end
it 'respects limit' do
@d.find({},:limit => 4).to_af.size.should == 4
@@ -40,22 +41,52 @@ def setup_coll
@d.find({},:limit => 2).rows
end
it 'respects skip' do
- @d.find({},:skip => 1).to_af.size.should == 5
- @d.find({},:skip => 1).map { |x| x['name'] }.sort.should == @all.reject { |x| x == 'Mike' }.sort
+ @d.find({},:skip => 1).to_af.size.should == @all.size - 1
+ @d.find({},:skip => 1).map { |x| x['name'] }.sort.should == @all.reject { |x| x == @locals.first }.sort
end
it 'respects skip whole collection' do
- @d.find({},:skip => 4).to_af.size.should == 2
+ @d.find({},:skip => 4).to_af.size.should == @all.size - 4
end
it 'wont return remote records that were skipped locally' do
- @d.local.save(@d.remote.find_one(:name => 'Randy'))
- @d.find({},:skip => 5).to_af.size.should == 1
+ @d.local.save(@d.remote.find_one(:name => @remotes.first))
+ @d.find({},:skip => 5).to_af.size.should == @all.size - 5
end
it 'respects skip and limit' do
@d.find({},:skip => 1, :limit => 4).to_af.size.should == 4
end
it 'count doesnt fetch records' do
mock.instance_of(Mongo::Cursor).to_a.times(0)
- @d.count.should == 6
+ @d.count.should == @all.size
+ end
+ # it 'abc' do
+ # @d.local.scope_gte('_id' => @start_time.to_small_mongo_id).count.should == 3
+ # end
+ context 'sorting' do
+ it 'honors sort order when retreiving all records' do
+ @d.find({},:sort => [['name','ascending']]).map { |x| x['name'] }.should == @all.sort
+ end
+ it 'honors reverse sort order when retreiving all records' do
+ @d.find({},:sort => [['name','descending']]).map { |x| x['name'] }.should == @all.sort.reverse
+ end
+ it 'honors sort order with a limit' do
+ exp = @all.sort[0...4]
+ @d.find({},:sort => [['name','ascending']], :limit => 4).map { |x| x['name'] }.should == exp
+ end
+ it 'honors sort order with a limit desc' do
+ exp = @all.sort.reverse[0...4]
+ @d.find({},:sort => [['name','descending']], :limit => 4).map { |x| x['name'] }.should == exp
+ end
+ it 'honors sort order with a skip' do
+ exp = @all.sort[1..-1]
+ @d.find({},:sort => [['name','ascending']], :skip => 1).map { |x| x['name'] }.should == exp
+ end
+ it 'honors sort order with a skip desc' do
+ exp = @all.sort.reverse[1..-1]
+ @d.find({},:sort => [['name','descending']], :skip => 1).map { |x| x['name'] }.should == exp
+ end
+ it 'when sorting with a limit, never retreives more than the limit from any one collection' do
+ @d.find({},:sort => [['name','ascending']], :limit => 2).raw_rows.size.should == 4
+ end
end
# it 'count honors remote deletes' do
# @d.remote.find.each { |x| @d.save(x) }
@@ -72,16 +103,16 @@ def setup_coll
@d.local.count.should == @locals.size + 1
end
it 'updating a non-dup shouldnt mark it as a dup' do
- r = @d.local.find_one(:name => 'Mike').merge(:foo => :bar)
+ r = @d.local.find_one(:name => @locals.first).merge(:foo => :bar)
@d.save(r)
@d.count.should == 6
- @d.local.find_one(:name => 'Mike')['_duplicate'].should be_nil
+ @d.local.find_one(:name => @locals.first)['_duplicate'].should be_nil
end
it 'saving a dup for first time should mark it as a dup' do
- r = @d.remote.find_one(:name => 'Randy')
+ r = @d.remote.find_one(:name => @remotes.first)
@d.save(r)
@d.count.should == 6
- @d.local.find_one(:name => 'Randy')['_duplicate'].should == true
+ @d.local.find_one(:name => @remotes.first)['_duplicate'].should == true
end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.