Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
465 views
in Technique[技术] by (71.8m points)

ruby on rails - Thinking Sphinx and acts_as_taggable_on plugin

I installed Sphinx and Thinking Sphinx for ruby on rails 2.3.2.

When I search without conditions search works ok. Now, what I'd like to do is filter by tags, so, as I'm using the acts_as_taggable_on plugin, my Announcement model looks like this:

class Announcement < ActiveRecord::Base

  acts_as_taggable_on :tags,:category

  define_index do
    indexes title, :as => :title, :sortable => true
    indexes description, :as => :description, :sortable => true
    indexes tags.name, :as => :tags
    indexes category.name, :as => :category

    has category(:id), :as => :category_ids
    has tags(:id), :as => :tag_ids
  end

For some reason, when I run the following command, it will bring just one announcement, that has nothing to do with what I expect. I've got many announcements, so I expected a lot of results instead.

Announcement.search params[:announcement][:search].to_s, :with => {:tag_ids => 1}, :page => params[:page], :per_page => 10

I guess something is wrong, and it's not searching correctly.

Can anyone give my a clue of what's going on?

Thanks, Brian

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Thinking Sphinx relies on associations in model. In common situations you only have to put index definition below your associations.

With acts_as_taggable_on plug-in you don't have tag-related associations in model file and when you write

indexes tags.name, :as => :tags

TS interprets it like:

CAST(`announcements`.`name` AS CHAR) AS `tags`

(look at sql_query in development.sphinx.conf, in my case). I suppose that you have attribute name in model Announcement and don't run into error when rebuild index.

But we expect:

CAST(GROUP_CONCAT(DISTINCT IFNULL(`tags`.`name`, '0') SEPARATOR ' ') AS CHAR) AS `tags`

and:

LEFT OUTER JOIN `taggings` ON (`announcements`.`id` = `taggings`.`taggable_id`)  
LEFT OUTER JOIN `tags` ON (`tags`.`id` = `taggings`.`tag_id`) AND taggings.taggable_type = 'Announcement'

To get things working just add tag-related associations in your model before you rebuild index:

class Announcement < ActiveRecord::Base

  acts_as_taggable_on :tags,:category

  has_many :taggings, :as => :taggable, :dependent => :destroy, :include => :tag, :class_name => "ActsAsTaggableOn::Tagging",
            :conditions => "taggings.taggable_type = 'Announcement'"
  #for context-dependent tags:
  has_many :category_tags, :through => :taggings, :source => :tag, :class_name => "ActsAsTaggableOn::Tag",
          :conditions => "taggings.context = 'categories'"

In define_index method:

indexes category_tags(:name), :as => :tags
has category_tags(:id), :as => :tag_ids, :facet => true

In controller:

@announcement_facets = Announcement.facets params[:search], :with => {:tag_ids => [...]} 
@announcements = @announcement_facets.for.paginate( :page => params[:page], :per_page => 10 )

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...