[Tradução] Acts_As_Ferret Tutorial

outubro 8th, 2007 | by Ramon Soares |

Bem eu tinha dito no post anterior que estava cansado de escrever por hoje, + andei brincando um pouco com o Ferret e Act_As_Ferret que é na mais simples das explicações é uma engine de busca por textos. Em minha busca por conteúdo de estudo encontrei com ajuda do grande guru um ótimo tutorial, e decidir meio que traduzi-lo + acrescentando algumas observações.

Segue a “tradução”:

Se você quer adicionar uma busca rápida por textos em sua aplicação, e não teve sorte com o que o MySQL oferece, ou quer trabalhar com algo um pouco mais customizavel (e bastante rápido). Este tutorial lhe mostrara exatamente como fazer.

  1. O Que é o Ferret?
  2. Acts_As_Ferret
  3. Uso Básico
  4. Busca com Paginação
  5. Busca Avançada
  6. Busca Fora dos Campos Padrões
  7. Classificação Avançada (???)
  8. Armazenando Campo (???)
  9. Highlighting
  10. Resultados Turbinados
  11. Uso em Produção

O que exatamente é o Ferret?

O Ferret é uma biblioteca de uma engine de busca de textos de alta performance para o Ruby baseada no Apache Lucene (que todo grande menino do java utiliza). Para instalar é muito simples:

gem install ferret

Então veio o Acts_As_Ferret

Felizmente para nos desenvolvedores Rail, Jens Kramer escreveu o Acts As Ferret, que nos propicia de forma muito simples a criação de um complexa index de busca em um curto período de tempo.

Instalação: (Via Sistema)

As versões superiores a 0.3.1 disponíveis pelo gem. E você pode usar:

gem install acts_as_ferret

isto ira instalar a ultima versão no seu repositório gem local. Em sua aplicação Rails, você devera adicionar o seguinte código em environment.rb

require 'acts_as_ferret'

Além disso, você deve copiar os scripts para iniciar e parar o o DRb Server e o arquivo de configuração do repositório gem para o seu projeto Rails:

cp /usr/lib/ruby/gems/1.8/gems/acts_as_ferret-0.4.1/script/ferret_st* script/
cp /usr/lib/ruby/gems/1.8/gems/acts_as_ferret-0.4.1/config/ferret_server.yml config/
Instalação: (Via Plugin)
ruby script/plugin install svn://projects.jkraemer.net/acts_as_ferret/tags/stable/acts_as_ferret

Uso Básico

Vamo começar com o mais simples dos exemplos e vamos avançar a partir disso.

A primeira coisa que você deverá fazer é ir no model em que você pretende adicionar um índice e adicionar no topo:

class Member < ActiveRecord::Base
  acts_as_ferret :fields => [:first_name, :last_name]
end

Como você pode ver, você vai especificar o nome dos campos que deseja indexar. Quando fizer uma busca, todos os campos especificados serão pesquisados e apenas Members serão retornados.

Como fazer um pesquisa simples

O Plugin Acts As Ferret adiciona métodos de busca adicionais aos Model do ActiveRecord. E ao contrario de outros tutoriais, vamos começar com:

find_id_by_contents

Portanto, se executamos:

total_results, members = Member.find_id_by_contents("Gregg")

Vai acontecer o seguinte:
1. A pasta /index/development/member dentro de sua aplicação rails é criada e é onde ficaram os arquivos de índice.
2. Todos os Members da minha consulta e seu primeiro/último nome serão adicionados ao índice. Agora todas as vezes que adicionar/atualizar/remover um Member, este índice será automaticamente atualizado. Se você precisar recriar o índice, basta remover a pasta correspondente e reiniciar o servidor, e o índice será recriado na próxima consulta a tabela.
3. O Acts As Ferret executa a função Ferret’s Search_Each no index.
4. É retornado o total de itens e os 10 primeiros resultados, no seguinte formato:

members = [
         {:model => "Member", :id => "4", :score => "1.0"},
         {:model => "Member", :id => "21", :score => "0.93211"},
         {:model => "Member", :id => "27", :score => "0.32212"}
         ]

Recebemos um Array com os 10 primeiros resultados (Foram mostrados apenas 3 acima) com o id e a relevância de cada um.
No entanto se por exemplo existir 40 resultados possíveis, só teremos retornados os 10 primeiros resultados.

E se quisermos mais de 10 resultados?

O find_id_by_contents tem um conjunto de opções que podem ser passados:

Opções:

  • offset:
    Default: 0
    Ajusta o offset do retorno. Isto é usado para paginar o resultado. Vamos supor que você mostre 10 resultados por pagina. Se você não encontrar o resultado desejado nos 10 primeiros resultados. Se você definir o :offset para 10 e vai ter os próximos 10 resultados.
  • limit:
    Default: 10
    Este é o numero de resultados que deve ser retornado. Defina :limit para :all para que seja retornado todos os resultados.

Outras opções podem ser encontradas aqui.

Se preferir, você pode usa find_id_by_contents passando com bloco de código:

results = []
total_results = Member.find_id_by_contents("Gregg") {|result|
        results.push result
}

Neste ponto você deve esta pensando: “Bem eu quero mostrar os resultados da pesquisa e não apenas os IDs e pra isso eu vou ter que consultar os Models”. Assim você pode acabar fazendo algo do tipo:

results = []
total_results = Member.find_id_by_contents("Gregg") {|result|
        results.push Member.find(result[:id])
}

No entanto existe uma maneira melhor!

Pra isso tem o find_by_contents.

@results = Member.find_by_contents("Gregg")

O find_by_contents faz o seguinte:

  • Primeiro chama o nosso amigo “find_id_by_contents” e pega os IDs.
  • Mantem todos os IDs retornado, em seguida, consulta os dados do Model. Portanto, se o Member 4, 21 e 27 foram retornados, ele ira fazer uma consulta para obter os dados atuais: select * from members where (members.id in (’4′, ‘21′, ‘27′))
  • Retorna um array com o resultado, que podemos considerar um Array com objetos ActiveRecord, mais que é na verdade um objeto ActsAsFerret:: SearchResults (com algumas características adicionais como mostrado a baixo).

Poderíamos fazer algo como:

members = Member.find_by_contents("Gregg")

# It gives us total hits!
puts "Total hits = #{members.total_hits}"
for member in members
   puts "#{member.first_name} #{member.last_name}"

   # And the search Score!
   puts "Search Score = #{member.ferret_score}"
end

Verifique que “total_hits” e “ferret_score” não são campos da tabela. São informações adicionadas pelo plugin.

E então, como eu posso paginar?

Post a Comment