I''m just wondering where I would put the pagination for search results when using "acts_as_ferret". At the moment my search code is.. def search @query = params[:query] || '''' unless @query.blank? @results = Tutorial.find_by_contents @query end end Cheers SchmakO -- Posted via http://www.ruby-forum.com/.
Hi! On Mon, May 01, 2006 at 08:55:22AM +0200, SchmakO wrote:> I''m just wondering where I would put the pagination for search results > when using "acts_as_ferret". > > At the moment my search code is.. > > def search > @query = params[:query] || '''' > unless @query.blank? > @results = Tutorial.find_by_contents @query > end > endfind_by_contents has two options suitable for paging: :first_doc (first result to retrieve) and :num_docs (number of results to retrieve). so to retrieve results 10 to 20, you would use @results = Tutorial.find_by_contents(@query,:first_doc=>10,:num_docs=>10) hth, Jens -- webit! Gesellschaft f?r neue Medien mbH www.webit.de Dipl.-Wirtschaftsingenieur Jens Kr?mer kraemer at webit.de Schnorrstra?e 76 Tel +49 351 46766 0 D-01069 Dresden Fax +49 351 46766 66
To add to what Jens said, you may find this code useful: In your model: def self.search(q, options = {}) return nil if q.nil? default_options = {:limit => 10, :page => 1} options = default_options.merge options options[:offset] = options[:limit] * (options[:page].to_i-1) ... snip ... num = INDEX.search_each(query, {:num_docs => options[:limit], :first_doc => options[:offset]}) do |doc, score| ... snip ... [num, results] end Notice that I return the total matches as num, plus the results. The total matches is necessary to generate a paginator across all the items. For the pagination, I created this simple method in my application controller (note it assumes a params[:page] being passed around): def pages_for(size, options = {}) default_options = {:per_page => 10} options = default_options.merge options pages = Paginator.new self, size, options[:per_page], (params[:page]||1) pages end And lastly, to use it in a controller: @total, @results = YourModel.search(@query, :page => (params[:page]||1) @result_pages = pages_for(@total) Tom On 5/3/06, Jens Kraemer <kraemer at webit.de> wrote:> Hi! > > On Mon, May 01, 2006 at 08:55:22AM +0200, SchmakO wrote: > > I''m just wondering where I would put the pagination for search results > > when using "acts_as_ferret". > > > > At the moment my search code is.. > > > > def search > > @query = params[:query] || '''' > > unless @query.blank? > > @results = Tutorial.find_by_contents @query > > end > > end > > find_by_contents has two options suitable for paging: > :first_doc (first result to retrieve) and > :num_docs (number of results to retrieve). > > so to retrieve results 10 to 20, you would use > @results = Tutorial.find_by_contents(@query,:first_doc=>10,:num_docs=>10) > > hth, > Jens > > > -- > webit! Gesellschaft f?r neue Medien mbH www.webit.de > Dipl.-Wirtschaftsingenieur Jens Kr?mer kraemer at webit.de > Schnorrstra?e 76 Tel +49 351 46766 0 > D-01069 Dresden Fax +49 351 46766 66 > _______________________________________________ > Ferret-talk mailing list > Ferret-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/ferret-talk >-- Tom Davies http://blog.atomgiant.com http://gifthat.com
Nice! This is very useful! What code did you snip out of the serach method? Is that required? Thanks. Tom Davies wrote:> To add to what Jens said, you may find this code useful: > > In your model: > > def self.search(q, options = {}) > return nil if q.nil? > default_options = {:limit => 10, :page => 1} > options = default_options.merge options > options[:offset] = options[:limit] * (options[:page].to_i-1) > ... snip ... > num = INDEX.search_each(query, {:num_docs => options[:limit], > :first_doc => options[:offset]}) do |doc, score| > ... snip ... > [num, results] > end > > Notice that I return the total matches as num, plus the results. The > total matches is necessary to generate a paginator across all the > items. > > For the pagination, I created this simple method in my application > controller (note it assumes a params[:page] being passed around): > > def pages_for(size, options = {}) > default_options = {:per_page => 10} > options = default_options.merge options > pages = Paginator.new self, size, options[:per_page], > (params[:page]||1) > pages > end > > And lastly, to use it in a controller: > @total, @results = YourModel.search(@query, :page => > (params[:page]||1) > @result_pages = pages_for(@total) > > Tom > > On 5/3/06, Jens Kraemer <kraemer at webit.de> wrote: >> > unless @query.blank? >> >> Ferret-talk mailing list >> Ferret-talk at rubyforge.org >> http://rubyforge.org/mailman/listinfo/ferret-talk >> > > > -- > Tom Davies > > http://blog.atomgiant.com > http://gifthat.com-- Posted via http://www.ruby-forum.com/.
I think the simplest way to attack this problem is just to write a paginator for an array of objects. Then you can just do your usual find_by_contents, with num_docs set to :all, and then just paginate the array that is returned. Tom Davies wrote:> To add to what Jens said, you may find this code useful: > > In your model: > > def self.search(q, options = {}) > return nil if q.nil? > default_options = {:limit => 10, :page => 1} > options = default_options.merge options > options[:offset] = options[:limit] * (options[:page].to_i-1) > ... snip ... > num = INDEX.search_each(query, {:num_docs => options[:limit], > :first_doc => options[:offset]}) do |doc, score| > ... snip ... > [num, results] > end > > Notice that I return the total matches as num, plus the results. The > total matches is necessary to generate a paginator across all the > items. > > For the pagination, I created this simple method in my application > controller (note it assumes a params[:page] being passed around): > > def pages_for(size, options = {}) > default_options = {:per_page => 10} > options = default_options.merge options > pages = Paginator.new self, size, options[:per_page], > (params[:page]||1) > pages > end > > And lastly, to use it in a controller: > @total, @results = YourModel.search(@query, :page => > (params[:page]||1) > @result_pages = pages_for(@total) > > Tom > > On 5/3/06, Jens Kraemer <kraemer at webit.de> wrote: >> > unless @query.blank? >> >> Ferret-talk mailing list >> Ferret-talk at rubyforge.org >> http://rubyforge.org/mailman/listinfo/ferret-talk >> > > > -- > Tom Davies > > http://blog.atomgiant.com > http://gifthat.com-- Posted via http://www.ruby-forum.com/.
I guess that''s sort of what you did, but I don''t think you need to define the self.search method. find_by_contents works just fine. Mike Michelson wrote:> I think the simplest way to attack this problem is just to write a > paginator for an array of objects. Then you can just do your usual > find_by_contents, with num_docs set to :all, and then just paginate the > array that is returned. > > >-- Posted via http://www.ruby-forum.com/.
The snipped out portion is just where you process the results. In my case, I am searching for gifts so here is how I search and collect the Gift objects: num = INDEX.search_each(query, {:num_docs => options[:limit], :first_doc => options[:offset]}) do |doc, score| logger.debug("Found doc: #{doc}, id: #{INDEX[doc][''id'']}, score: #{score}") gifts << Gift.find(INDEX[doc][''id'']) end Also, the reason I defined my own search method as opposed to using find_by_contents is because I am not using the acts_as_ferret plugin.>From looking at the acts_as_ferret code, it looks like you can justuse the SearchResults object returned by the find_by_contents since it also includes the total hits needed to create the Paginator pages. Tom On 7/5/06, guest <guest at guest.com> wrote:> > Nice! > > This is very useful! > > What code did you snip out of the serach method? Is that required? > > Thanks. > > > Tom Davies wrote: > > To add to what Jens said, you may find this code useful: > > > > In your model: > > > > def self.search(q, options = {}) > > return nil if q.nil? > > default_options = {:limit => 10, :page => 1} > > options = default_options.merge options > > options[:offset] = options[:limit] * (options[:page].to_i-1) > > ... snip ... > > num = INDEX.search_each(query, {:num_docs => options[:limit], > > :first_doc => options[:offset]}) do |doc, score| > > ... snip ... > > [num, results] > > end > > > > Notice that I return the total matches as num, plus the results. The > > total matches is necessary to generate a paginator across all the > > items. > > > > For the pagination, I created this simple method in my application > > controller (note it assumes a params[:page] being passed around): > > > > def pages_for(size, options = {}) > > default_options = {:per_page => 10} > > options = default_options.merge options > > pages = Paginator.new self, size, options[:per_page], > > (params[:page]||1) > > pages > > end > > > > And lastly, to use it in a controller: > > @total, @results = YourModel.search(@query, :page => > > (params[:page]||1) > > @result_pages = pages_for(@total) > > > > Tom > > > > On 5/3/06, Jens Kraemer <kraemer at webit.de> wrote: > >> > unless @query.blank? > >> > >> Ferret-talk mailing list > >> Ferret-talk at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/ferret-talk > >> > > > > > > -- > > Tom Davies > > > > http://blog.atomgiant.com > > http://gifthat.com > > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Ferret-talk mailing list > Ferret-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/ferret-talk >-- Tom Davies http://atomgiant.com http://gifthat.com
Oh, one more thing, I just looked and the find_by_contents didn''t support returning the total results when I wrote my original pagination post :) Also, I don''t think the current acts_as_ferret release supports it either (but the trunk does), so you may have to grab the trunk if you want to paginate in pure acts_as_ferret land. Tom On 7/7/06, Tom Davies <atomgiant at gmail.com> wrote:> The snipped out portion is just where you process the results. In my > case, I am searching for gifts so here is how I search and collect the > Gift objects: > > num = INDEX.search_each(query, {:num_docs => options[:limit], > :first_doc => options[:offset]}) do |doc, score| > logger.debug("Found doc: #{doc}, id: #{INDEX[doc][''id'']}, score: > #{score}") > gifts << Gift.find(INDEX[doc][''id'']) > end > > Also, the reason I defined my own search method as opposed to using > find_by_contents is because I am not using the acts_as_ferret plugin. > From looking at the acts_as_ferret code, it looks like you can just > use the SearchResults object returned by the find_by_contents since it > also includes the total hits needed to create the Paginator pages. > > Tom > > On 7/5/06, guest <guest at guest.com> wrote: > > > > Nice! > > > > This is very useful! > > > > What code did you snip out of the serach method? Is that required? > > > > Thanks. > > > > > > Tom Davies wrote: > > > To add to what Jens said, you may find this code useful: > > > > > > In your model: > > > > > > def self.search(q, options = {}) > > > return nil if q.nil? > > > default_options = {:limit => 10, :page => 1} > > > options = default_options.merge options > > > options[:offset] = options[:limit] * (options[:page].to_i-1) > > > ... snip ... > > > num = INDEX.search_each(query, {:num_docs => options[:limit], > > > :first_doc => options[:offset]}) do |doc, score| > > > ... snip ... > > > [num, results] > > > end > > > > > > Notice that I return the total matches as num, plus the results. The > > > total matches is necessary to generate a paginator across all the > > > items. > > > > > > For the pagination, I created this simple method in my application > > > controller (note it assumes a params[:page] being passed around): > > > > > > def pages_for(size, options = {}) > > > default_options = {:per_page => 10} > > > options = default_options.merge options > > > pages = Paginator.new self, size, options[:per_page], > > > (params[:page]||1) > > > pages > > > end > > > > > > And lastly, to use it in a controller: > > > @total, @results = YourModel.search(@query, :page => > > > (params[:page]||1) > > > @result_pages = pages_for(@total) > > > > > > Tom > > > > > > On 5/3/06, Jens Kraemer <kraemer at webit.de> wrote: > > >> > unless @query.blank? > > >> > > >> Ferret-talk mailing list > > >> Ferret-talk at rubyforge.org > > >> http://rubyforge.org/mailman/listinfo/ferret-talk > > >> > > > > > > > > > -- > > > Tom Davies > > > > > > http://blog.atomgiant.com > > > http://gifthat.com > > > > > > -- > > Posted via http://www.ruby-forum.com/. > > _______________________________________________ > > Ferret-talk mailing list > > Ferret-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/ferret-talk > > > > > -- > Tom Davies > > http://atomgiant.com > http://gifthat.com >-- Tom Davies http://atomgiant.com http://gifthat.com
Hello Jens, just a quick question about your code... if i am using this: @test = County.find_by_contents(@params[''search_string''],:first_doc=>0,:num_docs=>10) do i just setup up numbered links in my view to pass a variable to first_doc? so if i wanted to get the next set, id do: @test = County.find_by_contents(@params[''search_string''],:first_doc=>@params[''10''], :num_docs=>10) if this is the case, is there an easier way and also a way to count how many sets or how many pages there are in a table for a given query? would i just get a total from the array and then divide by 10 docs? etc...? thanks! Jens Kraemer wrote:> Hi! > > On Mon, May 01, 2006 at 08:55:22AM +0200, SchmakO wrote: >> end > find_by_contents has two options suitable for paging: > :first_doc (first result to retrieve) and > :num_docs (number of results to retrieve). > > so to retrieve results 10 to 20, you would use > @results = > Tutorial.find_by_contents(@query,:first_doc=>10,:num_docs=>10) > > hth, > Jens > > > -- > webit! Gesellschaft f?r neue Medien mbH www.webit.de > Dipl.-Wirtschaftsingenieur Jens Kr?mer kraemer at webit.de > Schnorrstra?e 76 Tel +49 351 46766 0 > D-01069 Dresden Fax +49 351 46766 66-- Posted via http://www.ruby-forum.com/.
On 10/17/06, koloa <none at none.com> wrote:> > > Hello Jens, just a quick question about your code... > > if i am using this: > > @test > County.find_by_contents(@params[''search_string''],:first_doc=>0,:num_docs=>10)For starters, :first_doc is now :offset and :num_docs is now :limit, as of Ferret 0.10.0.> do i just setup up numbered links in my view to pass a variable to > first_doc? so if i wanted to get the next set, id do: > > > @test > County.find_by_contents(@params[''search_string''],:first_doc=>@params[''10''], > :num_docs=>10)Strange parameter name but yes, that''s how you''d do it.> if this is the case, is there an easier way and also a way to count how > many sets or how many pages there are in a table for a given query? > would i just get a total from the array and then divide by 10 docs? > etc...?I''m not sure about easier way but you can get the total number of matching hits from @test.total_hits. On the other hand, @test.size will be the number of hits returned. Hope that answers your question, Dave
On Tue, Oct 17, 2006 at 09:30:50AM +0900, David Balmain wrote:> On 10/17/06, koloa <none at none.com> wrote:[..]> > > > @test > > County.find_by_contents(@params[''search_string''],:first_doc=>0,:num_docs=>10) > > For starters, :first_doc is now :offset and :num_docs is now :limit, > as of Ferret 0.10.0.right, though aaf still works with the old naming, too ;-) [..]> > if this is the case, is there an easier way and also a way to count how > > many sets or how many pages there are in a table for a given query? > > would i just get a total from the array and then divide by 10 docs? > > etc...? > > I''m not sure about easier way but you can get the total number of > matching hits from @test.total_hits. On the other hand, @test.size > will be the number of hits returned.exactly. I didn''t try this, but it should be possible to use a Rails Paginator to handle the whole pagination stuff. Jens -- webit! Gesellschaft f?r neue Medien mbH www.webit.de Dipl.-Wirtschaftsingenieur Jens Kr?mer kraemer at webit.de Schnorrstra?e 76 Tel +49 351 46766 0 D-01069 Dresden Fax +49 351 46766 66
hey guys, any idea how to use those options with multi_search I tried it on find_by_contents and it works fine, however, for multi_search i do: @results = User.multi_search(parse(@query),[Book],{:offset=>0,:limit=>5}) or @results = User.multi_search(parse(@query),[Book],:offset=>0,:limit=>5) and neither works, however I get no error either. Whats wrong? -- Posted via http://www.ruby-forum.com/.