Pergunta

Instalei a Esfinge e pensando na Esfinge para Ruby on Rails 2.3.2.

Quando pesquisar sem condições, a pesquisa funciona bem. Agora, o que eu gostaria de fazer é filtrar por tags, então, enquanto estou usando o plugin Acts_as_taggable_on, meu modelo de anúncio se parece com o seguinte:

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

Por alguma razão, quando eu executar o seguinte comando, trará apenas um anúncio, que não tem nada a ver com o que eu espero. Eu tenho muitos anúncios, então esperava muitos resultados.

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

Eu acho que algo está errado e não está pesquisando corretamente.

Alguém pode dar uma idéia do que está acontecendo?

Obrigado, Brian

Foi útil?

Solução

Pensar Sphinx depende de associações no modelo. Em situações comuns, você só precisa colocar a definição de índice abaixo de suas associações.

Com Atos_as_taggable_on plug-in você não tem associações relacionadas a tags no arquivo de modelo e quando você escreve

indexes tags.name ,: as =>: tags

TS interpreta como:

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

(Veja SQL_QUERY em desenvolvimento.sphinx.conf, no meu caso). Suponho que você tenha o nome de atributo no anúncio do modelo e não se depare com o erro de reconstrução.

Mas esperamos:

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

e:

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'

Para fazer as coisas funcionarem, basta adicionar associações relacionadas a tags em seu modelo antes de reconstruir o índice:

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'"

Dentro define_index método:

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

No controlador:

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

Outras dicas

Eu descobri que simplesmente definir o índice assim:

Class Thing < ActiveRecord::Base    

acts_as_taggable

     define_index do
        ..other indexing...
        indexes taggings.tag.name, :as => :tags
     end
end

funcionou bem.

Uma possibilidade é que você precise declarar o tipo para tag_ids como: multi porque o TS pode ficar confuso (acabei de descobrir isso aqui http://groups.google.com/group/thinking-sphinx/browse_thread/thread/9bd4572398f35712/14d4c1503f5959a9?lnk=gst&q=yanowitz#14d4c1503f5959a9).

Mas por que não usar os nomes de tags para pesquisar? Por exemplo,

Announcement.search params[:announcement][:search].to_s, :conditions => {:tags => "my_tag"}, :page => params[:page], :per_page => 10

Ou, se você precisar procurar várias tags:

Announcement.search( "#{params[:announcement][:search].to_s} (@tags my_tag | @tags your_tag)", :page => params[:page], :per_page => 10 )

(Como de lado, você pode querer higienizar/remover caracteres de controle de esfinge da consulta fornecida pelo usuário antes de usá-la).

Para a depuração, eu entrava em console e retirava sua consulta o máximo possível (eliminaria argumentos de paginação, até a consulta (basta fazer ""), etc.).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top