[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.
- O Que é o Ferret?
- Acts_As_Ferret
- Uso Básico
- Busca com Paginação
- Busca Avançada
- Busca Fora dos Campos Padrões
- Classificação Avançada (???)
- Armazenando Campo (???)
- Highlighting
- Resultados Turbinados
- 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.