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 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
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/.