Skip to content

Commit

Permalink
Added offset and count options for Resultset
Browse files Browse the repository at this point in the history
  • Loading branch information
haslo committed Dec 3, 2015
1 parent acfba8e commit aade48b
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
24 changes: 17 additions & 7 deletions lib/xapian_db/resultset.rb
Expand Up @@ -45,7 +45,9 @@ class Resultset < Array
# Pass nil to get an empty result set.
# @param [Hash] options
# @option options [Integer] :db_size The current size (nr of docs) of the database
# @option options [Integer] :limit The maximum number of documents to retrieve
# @option options [Integer] :limit The maximum number of documents to retrieve (in total, not per request)
# @option options [Integer] :offset The index of the first result to retrieve
# @option options [Integer] :count The maximum number of documents to retrieve per request (analogous to "limit" in SQL)
# @option options [Integer] :page (1) The page number to retrieve
# @option options [Integer] :per_page (10) How many docs per page? Ignored if a limit option is given
# @option options [String] :spelling_suggestion (nil) The spelling corrected query (if a language is configured)
Expand All @@ -56,25 +58,33 @@ def initialize(enquiry, options={})
db_size = params.delete :db_size
@spelling_suggestion = params.delete :spelling_suggestion
limit = params.delete :limit
offset = params.delete :offset
count = params.delete :count
page = params.delete :page
per_page = params.delete :per_page
raise ArgumentError.new "unsupported options for resultset: #{params}" if params.size > 0
raise ArgumentError.new "db_size option is required" unless db_size
raise ArgumentError.new "impossible combination of parameters" unless (page.nil? && per_page.nil?) || (offset.nil? && count.nil?)

calculated_page = offset.nil? || count.nil? ? nil : (offset.to_f / count.to_f) + 1

limit = limit.nil? ? db_size : limit.to_i
per_page = per_page.nil? ? limit : per_page.to_i
page = page.nil? ? 1 : page.to_i
offset = (page - 1) * per_page
count = offset + per_page < limit ? per_page : limit - offset
per_page = per_page.nil? ? (count.nil? ? limit.to_i : count.to_i) : per_page.to_i
page = page.nil? ? (calculated_page.nil? ? 1 : calculated_page) : page.to_i
offset = offset.nil? ? (page - 1) * per_page : offset.to_i
count = count.nil? ? (offset + per_page < limit ? per_page : limit - offset) : count.to_i

raise ArgumentError.new "page #{page} does not exist" if (page - 1) * per_page > db_size

result_window = enquiry.mset(offset, count)
@hits = result_window.matches_estimated
return build_empty_resultset if @hits == 0
raise ArgumentError.new "page #{@page} does not exist" if @hits > 0 && offset >= limit

raise ArgumentError.new "page #{page} does not exist within given limit" if @hits > 0 && offset >= limit

self.replace result_window.matches.map{|match| decorate(match).document}
@total_pages = (@hits / per_page.to_f).ceil
@current_page = page
@current_page = (page == page.to_i) ? page.to_i : page
@limit_value = per_page
end

Expand Down
34 changes: 33 additions & 1 deletion spec/xapian_db/resultset_spec.rb
Expand Up @@ -75,6 +75,29 @@
expect(resultset.size).to eq(2)
expect(resultset.current_page).to eq(1)
expect(resultset.total_pages).to eq(2)
expect(resultset.limit_value).to eq(2)
expect(resultset.total_count).to eq(@matches.size)
expect(resultset.total_entries).to eq(@matches.size)
end

it "accepts a count option (as a string or an integer)" do
allow(@mset).to receive(:matches).and_return(@matches[0..1])
resultset = XapianDb::Resultset.new(@enquiry, :db_size => @matches.size, :count => "2")
expect(resultset.hits).to eq(3)
expect(resultset.size).to eq(2)
expect(resultset.current_page).to eq(1)
expect(resultset.total_pages).to eq(2)
expect(resultset.total_count).to eq(@matches.size)
expect(resultset.total_entries).to eq(@matches.size)
end

it "accepts an offset option (as a string or an integer)" do
allow(@mset).to receive(:matches).and_return(@matches[1..2])
resultset = XapianDb::Resultset.new(@enquiry, :db_size => @matches.size, :count => "2", offset: "1")
expect(resultset.hits).to eq(3)
expect(resultset.size).to eq(2)
expect(resultset.current_page).to eq(1.5)
expect(resultset.total_pages).to eq(2)
expect(resultset.total_count).to eq(@matches.size)
expect(resultset.total_entries).to eq(@matches.size)
end
Expand Down Expand Up @@ -110,7 +133,16 @@
end

it "raises an exception if page is requested that does not exist" do
expect{XapianDb::Resultset.new(@enquiry, :db_size => @matches.size, :per_page => 2, :page => 3)}.to raise_error "page does not exist"
expect{XapianDb::Resultset.new(@enquiry, :db_size => @matches.size, :per_page => 2, :page => 3)}.to raise_error ArgumentError, "page 3 does not exist"
end

it "raises an exception if page is requested that does not exist within given limit" do
expect{XapianDb::Resultset.new(@enquiry, :db_size => @matches.size, :per_page => 2, :page => 2, limit: 2)}.to raise_error ArgumentError, "page 2 does not exist within given limit"
end

it "raises an exception if elements of both page / per_page and offset / count are given" do
expect{XapianDb::Resultset.new(@enquiry, :db_size => @matches.size, :per_page => 2, :page => 2, offset: 1, count: 3)}.to raise_error ArgumentError, "impossible combination of parameters"
expect{XapianDb::Resultset.new(@enquiry, :db_size => @matches.size, :per_page => 2, offset: 1)}.to raise_error ArgumentError, "impossible combination of parameters"
end

it "should populate itself with found xapian documents" do
Expand Down

0 comments on commit aade48b

Please sign in to comment.