Search on data accross many tables, linked by belongs_to

I am using Ferret and acts_as_ferret, as my search back-end for my Rails
project. I have a question about using acts_as_ferret on a main table
that is linked to other tables by foreign keys. Is there a way to
include the information linked by the belongs_to keyword in the search
results ?

As an example, let’s say I have a main table ‘posts’:

=============================
| posts

id
title
content
category_id

where category_id is a foreign key pointing to a row of the table
‘categories’:

=============================
| categories

id
name

My Rails models are then:

class Post < ActiveRecord::Base
belongs_to :category
acts_as_ferret :fields => [ ‘title’, ‘content’ ]
end

class Category < ActiveRecord::Base
has_many :posts
end

I would want to be able to change the following line
acts_as_ferret :fields => [ ‘title’, ‘content’ ]
to
acts_as_ferret :fields => [ ‘title’, ‘content’, ‘category.name’
]

and have Ferret search for records specified by title, content and
category name.

Is there an known solution to my problem ? In Ferret, how can I specify
a search accross many tables for results returning only a main class (in
the example, search all posts that have a certain category name by just
typing that cateogry name as the query) ? Do I have to create a new
model class PostIndex that gathers all the information just for the
indexing, even though the information is not stored that way in the
database ?

Thanks a lot for your help,
Maxime C.

Hi Maxime,

On Sat, Jul 08, 2006 at 12:13:53AM +0200, Maxime C. wrote:

I am using Ferret and acts_as_ferret, as my search back-end for my Rails
project. I have a question about using acts_as_ferret on a main table
that is linked to other tables by foreign keys. Is there a way to
include the information linked by the belongs_to keyword in the search
results ?

[…]

I would want to be able to change the following line
acts_as_ferret :fields => [ ‘title’, ‘content’ ]
to
acts_as_ferret :fields => [ ‘title’, ‘content’, ‘category.name’
]

and have Ferret search for records specified by title, content and
category name.

you could use

acts_as_ferret :fields => [ ‘title’, ‘content’, :category_name]
def category_name
category.name
end

to achieve this.

Jens


webit! Gesellschaft für neue Medien mbH www.webit.de
Dipl.-Wirtschaftsingenieur Jens Krämer [email protected]
Schnorrstraße 76 Tel +49 351 46766 0
D-01069 Dresden Fax +49 351 46766 66

Thanks Jens, I didn’t know it was that simple !

you could use

acts_as_ferret :fields => [ ‘title’, ‘content’, :category_name]
def category_name
category.name
end

to achieve this.

Jens

On Thu, Jul 13, 2006 at 04:59:02PM +0200, Guest wrote:

Hmm. I tried doing it with a few levels of nesting like:

acts_as_ferret :fields => { :menu_item_name, ‘city’, ‘state’, ‘zip’ }

def menu_item_name
menus.menu_categories.menu_items.name
end

And I don’t get any results.

that can have many reasons :wink:
Basically, what you do in the method is irrelevant to ferret, it just
indexes what is returned by the method.

You should see what fields acts_as_ferret adds to the index
in your development log when you save a record.
please check there if it adds what you want.

Jens


webit! Gesellschaft für neue Medien mbH www.webit.de
Dipl.-Wirtschaftsingenieur Jens Krämer [email protected]
Schnorrstraße 76 Tel +49 351 46766 0
D-01069 Dresden Fax +49 351 46766 66

Hmm. I tried doing it with a few levels of nesting like:

acts_as_ferret :fields => { :menu_item_name, ‘city’, ‘state’, ‘zip’ }

def menu_item_name
menus.menu_categories.menu_items.name
end

And I don’t get any results.

The tables in the DB are like:

menus

menu_categories
menu_id

menu_items
menu_category_id

Am I missing something???

Maxime C. wrote:

Thanks Jens, I didn’t know it was that simple !

you could use

acts_as_ferret :fields => [ ‘title’, ‘content’, :category_name]
def category_name
category.name
end

to achieve this.

Jens

Wait so, now I added acts_as_ferret in the menu_item model, and it looks
as it’s it’s being indexed in the log, but I still don’t get the
results.

Hmm…

Guest wrote:

OK, when I create the top level item, it indexes the fields, but since
I’m creating the menus and menu_items separately it doesn’t look like
those are getting indexed according to the log. Do I have to set
something else up?

Thanks Jens!

Jens K. wrote:

On Thu, Jul 13, 2006 at 04:59:02PM +0200, Guest wrote:

Hmm. I tried doing it with a few levels of nesting like:

acts_as_ferret :fields => { :menu_item_name, ‘city’, ‘state’, ‘zip’ }

def menu_item_name
menus.menu_categories.menu_items.name
end

And I don’t get any results.

that can have many reasons :wink:
Basically, what you do in the method is irrelevant to ferret, it just
indexes what is returned by the method.

You should see what fields acts_as_ferret adds to the index
in your development log when you save a record.
please check there if it adds what you want.

Jens


webit! Gesellschaft f�r neue Medien mbH www.webit.de
Dipl.-Wirtschaftsingenieur Jens Kr�mer [email protected]
Schnorrstra�e 76 Tel +49 351 46766 0
D-01069 Dresden Fax +49 351 46766 66

OK, when I create the top level item, it indexes the fields, but since
I’m creating the menus and menu_items separately it doesn’t look like
those are getting indexed according to the log. Do I have to set
something else up?

Thanks Jens!

Jens K. wrote:

On Thu, Jul 13, 2006 at 04:59:02PM +0200, Guest wrote:

Hmm. I tried doing it with a few levels of nesting like:

acts_as_ferret :fields => { :menu_item_name, ‘city’, ‘state’, ‘zip’ }

def menu_item_name
menus.menu_categories.menu_items.name
end

And I don’t get any results.

that can have many reasons :wink:
Basically, what you do in the method is irrelevant to ferret, it just
indexes what is returned by the method.

You should see what fields acts_as_ferret adds to the index
in your development log when you save a record.
please check there if it adds what you want.

Jens


webit! Gesellschaft f�r neue Medien mbH www.webit.de
Dipl.-Wirtschaftsingenieur Jens Kr�mer [email protected]
Schnorrstra�e 76 Tel +49 351 46766 0
D-01069 Dresden Fax +49 351 46766 66

Hi!

On Thu, Jul 13, 2006 at 07:53:36PM +0200, Guest wrote:

Wait so, now I added acts_as_ferret in the menu_item model, and it looks
as it’s it’s being indexed in the log, but I still don’t get the
results.

calling acts_as_ferret in the MenuItem class will create a separate
index for MenuItems, this is probably not what you want.

The problem is, that ferret only can index what your menu_item_name
method delivers when the object is saved. If you save the object before
creating the menus and menu_items, there’s nothing to index.

You could try to create the menus and menu_items first, then add them to
the object to be indexed and then call save.

Or just call save another time after you created the menus.

btw, ‘menuitems’ sounds like it is a collection of menuitems, so what
should ‘menuitems.name’ deliver ? Maybe you want something like

menuitems.inject(‘’) { |value, item| value << " #{item.name}" }

concatenating the names of all menuitems to one string which then would
be indexed ? The same for ‘menus’, sounds like a has_many relationship,
too.

I’m sure we’ll get this right somehow :wink:

Jens

Thanks Jens!

end

Posted via http://www.ruby-forum.com/.


Ferret-talk mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/ferret-talk

webit! Gesellschaft für neue Medien mbH www.webit.de
Dipl.-Wirtschaftsingenieur Jens Krämer [email protected]
SchnorrstraÃ?e 76 Tel +49 351 46766 0
D-01069 Dresden Fax +49 351 46766 66

Should this be able to work from the Console? For example, let’s assume
there is a Post record with a Category name of “Help”…

Post.find_by_contents(“Help”)

For some reason this does not generate any results…

Maxime C. wrote:

Thanks Jens, I didn’t know it was that simple !

you could use

acts_as_ferret :fields => [ ‘title’, ‘content’, :category_name]
def category_name
category.name
end

to achieve this.

Jens

On Tue, Nov 28, 2006 at 01:36:43AM +0100, John Perkins wrote:

Should this be able to work from the Console? For example, let’s assume
there is a Post record with a Category name of “Help”…

Post.find_by_contents(“Help”)

For some reason this does not generate any results…

it should work from the console. what if you do Post.rebuild_index
before the find_by_contents call ?

Jens


webit! Gesellschaft für neue Medien mbH www.webit.de
Dipl.-Wirtschaftsingenieur Jens Krämer [email protected]
Schnorrstraße 76 Tel +49 351 46766 0
D-01069 Dresden Fax +49 351 46766 66