segunda-feira, 6 de outubro de 2008

Busca em Textos com Sphinx

Sphinx eh um otimo servidor de busca em texto. Hoje vou demonstrar
como voce pode ter um site com um engine de busca rodando em sphinx
atraves de um plugin em Rails.

Para iniciar, precisamos instalar o Sphinx. Basta seguir os passos
a seguir:

wget http://sphinxsearch.com/downloads/sphinx-0.9.8.tar.gz
tar xvzf sphinx-0.9.8.tar.gz
cd sphinx-0.9.8/
./configure
make
(sudo) make install

Uma vez com o sphinx instalado, va para a sua area de trabalho e crie
o projeto.
IMPORTANTE: O Sphinx nao funciona com sqlite, entao precisamos alterar
nosso databases.yml para funcionar com o Mysql.

rails mysite
cd mysite

Edite o seu databases.yml:

config/databases.yml

development:
adapter: mysql
database: mysite_dev
username: root
password:

test:
adapter: mysql
database: mysite_test
username: root
password:

Vamos criar os bancos!

rake db:create:all

Finalmente, instale o plugin:

script/plugin install git://github.com/freelancing-god/thinking-sphinx.git

Com o plugin instalado e funcionando, vamos criar um scaffold padrao. No
nosso caso, nosso projeto sera um website simples, com paginas gerenciadas em
um CMS e com busca por conteudo dentro das paginas. (Poderiamos inclusive utilizar
o projeto anterior que funciona com FCKEditor)

script/generate scaffold page title:string body:text published:boolean

Nao vamos esquecer de migrar a versao do banco, para que nosso schema seja
criado para a tabela pages.

rake db:migrate

E vamos criar um controller separado que ira conter nossa pagina inicial com
o campo de busca.

script/generate controller main index

E nao podemos esquecer de definir em nosso routes.rb que este eh nosso controller
root (padrao) em nosso projeto

config/routes.rb

map.root :controller => 'main'

Por ultimo, vamos remover o arquivo index.html

rm public/index.html

Inicie o server do seu projeto:

script/server

Ok, estamos quase prontos para comecar a instalar nossa busca. O que precisamos agora,
claro, eh criar algumas paginas. Vou deixar isso por sua conta. Siga para o proximo
passo quando tiver umas 4, 5 paginas criadas.

... criando paginas ... :-)

Se vc ja critou suas paginas, entao agora eh hora de colocar nosso plugin pra funcionar.
Vamos comecar pela parte facil, que eh justamente adicionar o campo de busca na nossa action principal, index, dentro do nosso controller principal, MainController:

app/views/main/index.html.erb


<h1>Main page</h1>
<%= form_tag %>
<%= text_field_tag :query %>
<%= submit_tag 'Search' %>
<hr/>
<% if @pages %>
<h3> Sua busca por '<%= @query %>' retornou <%= @pages.size %> resultados:</h3>
<ol>
<% for page in @pages %>
<li><%= link_to page.title, :controller => 'pages', :action => 'show', :id => page.id %></li>
<% end %>
</ol>
<% else %>
<h3> Sua busca por '<%= @query %>' nao retornou nenhum resultado</h3>
<% end %>
</form>



Ok, tudo indica que nosso View ja esta completo. Agora precisamos cuidar do controller.
Mas antes, precisamos identificar no nosso Model (Page) quais os campos que vao ser
indexaveis pela busca (e, consequentemente, buscaveis por ela)

No nosso caso, eh interessante indexar 2 campos do nosso modelo Page: title e body.
Para isto, basta adicionar o bloco define_index na sua classe:

app/models/page.rb

class Page < ActiveRecord::Base

define_index do
indexes title
indexes body
end

end

Muito bem. Model e View estao prontos. Agora precisamos cuidar do controller, que
sinceramente eh o mais facil de todos:


app/controllers/main_controller.rb

class MainController < ApplicationController

def index
@pages = Page.search params[:query]
@query = params[:query]
end

end

Agora que temos nosso plugin instalado, e o controller pronto, precisamos indexar
o conteudo de pages no sphinx, e depois iniciar seu server.

Para isto, temos 2 Rake tasks:


rake thinking_sphinx:index
rake thinking_sphinx:start

Ou, se voce preferir, tambem temos as mesmas rake tasks com um nome um pouco mais
curto:

rake ts:in
rake ts:start

IMPORTANTE: Sempre que uma pagina for alterada ou incluida no banco de dados, precisamos
rodar novamente o index do Sphinx. Podemos no futuro discutir uma forma de realizar isto
de uma forma periodica dentro do rails. Por hora, talvez seja interessante executar como
uma tarefa no crontab.

Inicie o server:


script/server

Agora eh so comecar a utilizar sua busca. No proximo post vou demonstrar como adicionar
paginacao nos resultados com um plugin de paginacao bem popular para Rails.

Um comentário:

Norba disse...

Marcelo, obrigado pelo post. Salvou minha vida. Eu estou desenvolvendo um sistema de leis, e isso era o principal que eu precisava, fiz uma comparação aqui com o plugin do thinking_sphinx e busca normal no banco. Perfeito.