Forum: Ferret pagination in acts_as_ferret

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
D1484874233447ef640f69808aa7aef5?d=identicon&s=25 SchmakO (Guest)
on 2006-05-01 08:55
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
C9dd93aa135988cabf9183d3210665ca?d=identicon&s=25 Jens Kraemer (Guest)
on 2006-05-03 19:08
(Received via mailing list)
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@webit.de
Schnorrstraße 76                         Tel +49 351 46766  0
D-01069 Dresden                          Fax +49 351 46766 66
22580f640e491f0920a192610d1df393?d=identicon&s=25 Tom Davies (Guest)
on 2006-05-05 18:42
(Received via mailing list)
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@webit.de> wrote:
> >     unless @query.blank?
>
> Ferret-talk mailing list
> Ferret-talk@rubyforge.org
> http://rubyforge.org/mailman/listinfo/ferret-talk
>


--
Tom Davies

http://blog.atomgiant.com
http://gifthat.com
Abb249055208c7af4d35568e422dfd63?d=identicon&s=25 guest (Guest)
on 2006-07-05 18:35
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@webit.de> wrote:
>> >     unless @query.blank?
>>
>> Ferret-talk mailing list
>> Ferret-talk@rubyforge.org
>> http://rubyforge.org/mailman/listinfo/ferret-talk
>>
>
>
> --
> Tom Davies
>
> http://blog.atomgiant.com
> http://gifthat.com
1b6d62d8e9d71268bfe34fbfa5ca0b8b?d=identicon&s=25 Mike Michelson (michelson)
on 2006-07-06 13:05
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@webit.de> wrote:
>> >     unless @query.blank?
>>
>> Ferret-talk mailing list
>> Ferret-talk@rubyforge.org
>> http://rubyforge.org/mailman/listinfo/ferret-talk
>>
>
>
> --
> Tom Davies
>
> http://blog.atomgiant.com
> http://gifthat.com
1b6d62d8e9d71268bfe34fbfa5ca0b8b?d=identicon&s=25 Mike Michelson (michelson)
on 2006-07-06 13:19
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.
>
>
>
22580f640e491f0920a192610d1df393?d=identicon&s=25 Tom Davies (Guest)
on 2006-07-07 14:49
(Received via mailing list)
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@guest.com> wrote:
> Tom Davies wrote:
> >     num = INDEX.search_each(query, {:num_docs => options[:limit],
> > controller (note it assumes a params[:page] being passed around):
> >   @total, @results = YourModel.search(@query, :page =>
> >> http://rubyforge.org/mailman/listinfo/ferret-talk
> --
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> Ferret-talk mailing list
> Ferret-talk@rubyforge.org
> http://rubyforge.org/mailman/listinfo/ferret-talk
>


--
Tom Davies

http://atomgiant.com
http://gifthat.com
22580f640e491f0920a192610d1df393?d=identicon&s=25 Tom Davies (Guest)
on 2006-07-07 15:04
(Received via mailing list)
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@gmail.com> wrote:
>
> > Nice!
> > >
> > >     ... snip ...
> > >   def pages_for(size, options = {})
> > >   @result_pages = pages_for(@total)
> > >
> > _______________________________________________
> http://gifthat.com
>


--
Tom Davies

http://atomgiant.com
http://gifthat.com
3eda6fcd3204ef285fa52176c28c4d3e?d=identicon&s=25 koloa (Guest)
on 2006-10-17 00:26

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@webit.de
> Schnorrstra�e 76                         Tel +49 351 46766  0
> D-01069 Dresden                          Fax +49 351 46766 66
B5e329ffa0cc78efbfc7ae2d084c149f?d=identicon&s=25 David Balmain (Guest)
on 2006-10-17 02:36
(Received via mailing list)
On 10/17/06, koloa <none@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
C9dd93aa135988cabf9183d3210665ca?d=identicon&s=25 Jens Kraemer (Guest)
on 2006-10-17 13:59
(Received via mailing list)
On Tue, Oct 17, 2006 at 09:30:50AM +0900, David Balmain wrote:
> On 10/17/06, koloa <none@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@webit.de
Schnorrstraße 76                         Tel +49 351 46766  0
D-01069 Dresden                          Fax +49 351 46766 66
525128e48ca2b4c7fb6176ea166fccfd?d=identicon&s=25 Eric G. (gotskill10)
on 2006-10-23 00:40
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?
9a7026b028a19715c954a2dfb81aa74a?d=identicon&s=25 Robert Dempsey (robertonrails)
on 2007-01-26 00:04
This topic is locked and can not be replied to.