Questions about table association while using acts_as_ferret


#1

Hi all,

I’m quite new to ferret and acts_as_ferret and what to see if I can
implement the following requirement using them.

Suppose I have two model classes: Article and Comment. It’s obvious that
one article may have many comments, so this is a one-many relationship.
If I want to add full text search to these models, I’m supposed to use
acts_as_ferret in both of the classes.

Now say I what to search for “rails” in all of these documents, ferret
will simply return all the models it found, say article1, comment1 and
comment2. The problem is that, there is a chance(and not that small)
that comment1 or/and comment2 belong(s) to article1, in which case I
want to show just article1 with all its comments.

Of course I can go through the result set and write some logic to do
this. But I think acts_as_ferret should be able to solve at least part
of this problem. Is there an existing way to do this? If not, is there
any thought about adding this in the future?

Thanks.


#2

On Tue, Apr 24, 2007 at 01:43:17PM +0200, Allen Young wrote:

Hi all,

I’m quite new to ferret and acts_as_ferret and what to see if I can
implement the following requirement using them.

Suppose I have two model classes: Article and Comment. It’s obvious that
one article may have many comments, so this is a one-many relationship.
If I want to add full text search to these models, I’m supposed to use
acts_as_ferret in both of the classes.

That depends. If you are not interested in the single comment, but
always want to present the article it belongs to to the user, add a
method to Article that retrieves the contents from all the comments and
index the result of this method along with the article.
No need for the Comment class to be acts_as_ferret enabled in this case.

Jens

PS: to index the result of an instance method, just specify the method
name as a field in your call to acts_as_ferret, as you would do with any
database backed field.


Jens Krämer
webit! Gesellschaft für neue Medien mbH
Schnorrstraße 76 | 01069 Dresden
Telefon +49 351 46766-0 | Telefax +49 351 46766-66
removed_email_address@domain.invalid | www.webit.de

Amtsgericht Dresden | HRB 15422
GF Sven Haubold, Hagen Malessa


#3

Thanks Jens, I think that would be good enough.


#4

Hi,

as I just happened to explain in a previous post, Ferret can index data
returned from arbitrary methods, as well as ActiveRecord attributes.

you could Ferret index only your Article model and write a method, say
comment_content, that returns the content of all the comments, and index
that.

It does mean that you’ll need to reindex the associated Article when a
comment is added/updated (an after_save method on your Comment method
will do).

Tbh though, it’s really not very scalable because the entire content of
all the comments for the associated Article needs to be reindexed each
time. If you’re looking at a lot of comments here, then this might not
be the best solution.

Anyone know if there is a way to update an index field by merging in new
content, rather than having to replace it?

John.

On Tue, 2007-04-24 at 13:43 +0200, Allen Young wrote:

Now say I what to search for “rails” in all of these documents, ferret
Thanks.


http://johnleach.co.uk


#5

On Tue, Apr 24, 2007 at 02:54:27PM +0200, Allen Young wrote:

John L. wrote:

It does mean that you’ll need to reindex the associated Article when a
comment is added/updated (an after_save method on your Comment method
will do).

Absolutely. That’s why I asked if AAF could do something for us, say add
some parameters to acts_as_ferret to delcare the association and AAF
would do the after_save thing automatically.

Good point, I’ll think about how this could be done.

Ideally one would only need to specify the relationship itself as a
field, and let aaf rely on the related objects to implement some method
returning the textual content for indexing:

class Article
has_many :comments
acts_as_ferret :fields => [ :title , :body, :comments ]
end

class Comment
belongs_to :article
def to_ferret
“#{title} #{body}”
end
end

Finding out the Comment class from looking at the relationship should be
possible as AR does exactly the same.
What do you think?

Jens


Jens Krämer
webit! Gesellschaft für neue Medien mbH
Schnorrstraße 76 | 01069 Dresden
Telefon +49 351 46766-0 | Telefax +49 351 46766-66
removed_email_address@domain.invalid | www.webit.de

Amtsgericht Dresden | HRB 15422
GF Sven Haubold, Hagen Malessa


#6

Jens K. wrote:

Good point, I’ll think about how this could be done.

Ideally one would only need to specify the relationship itself as a
field, and let aaf rely on the related objects to implement some method
returning the textual content for indexing:

class Article
has_many :comments
acts_as_ferret :fields => [ :title , :body, :comments ]
end

class Comment
belongs_to :article
def to_ferret
“#{title} #{body}”
end
end

Finding out the Comment class from looking at the relationship should be
possible as AR does exactly the same.
What do you think?

Well, I think this would be fine for most of the cases, maybe you could
give a default implementation of “to_ferret” method which return a
string contains all the columns except “id” but I’m not sure if this is
a good idea anyway.

Another thing is how to deal with the multi-layer associations. Say
“Comment” has many “SomethingElse”. Now I want to treat an article, all
its comments and all the comments’ something_elses as a single item in
ferret. Then I’d have to define the “to_ferret” method in a more
complicated way(loop all the associations and get their contents).

The problem here is that any ActiveRecord model which has
“acts_as_ferret” declaration will be indexed as an individual item by
ferret. If I can use something like “acts_as_ferret_child” to tell
ferret that I want to index a model as part of another model rather than
an individual one, then the whole structure should be clear and simple.
For example:

Class Article << ActiveRecord::Base

This tells ferret to index article model as a single item.

acts_as_ferret
has_many :comments
end

Class comment << ActiveRecord::Base

This tells ferret to index comments as part of its parent article.

acts_as_ferret_child :parent => :article
belongs_to :article
end

I’m not sure whether this is feasible but I think it’s possible. And I
think there should be a way to automatically find the relationships
between models after they’ve declared by “has_many” .etc. If I’m right,
then we can get ride of the “:parent” parameter.


#7

John L. wrote:

It does mean that you’ll need to reindex the associated Article when a
comment is added/updated (an after_save method on your Comment method
will do).

Absolutely. That’s why I asked if AAF could do something for us, say add
some parameters to acts_as_ferret to delcare the association and AAF
would do the after_save thing automatically.