SlideShare una empresa de Scribd logo
1 de 25
Descargar para leer sin conexión
Busca	
  textual	
  com	
  
Rais,	
  Solr	
  e	
  Sunspot	
  

  @mauriciojr	
  –	
  h-p://techbot.me/	
  
Who?	
  
•  Maurício	
  Linhares	
  
   •    @mauriciojr	
  
   •    h-p://techbot.me/	
  
   •    Developer	
  da	
  OfficeDrop.com	
  
   •    Professor	
  na	
  Faculdade	
  iDez	
  
   •    JUGleader	
  do	
  PBJUG	
  
“LIKE”	
  considered	
  evil	
  
•  Consultas	
  que	
  usam	
  LIKE	
  só	
  são	
  eficientes	
  se	
  a	
  coluna	
  esPver	
  
   indexada	
  e	
  for	
  uma	
  busca	
  de	
  prefixo:	
  
   •  “josé%”	
  
   •  “maria%”	
  


•  Alguns	
  bancos	
  tem	
  um	
  limite	
  de	
  caracteres	
  que	
  podem	
  ser	
  
   indexado	
  em	
  campos	
  textuais;	
  

•  Bancos	
  de	
  dados	
  relacionais	
  normalmente	
  não	
  são	
  capazes	
  de	
  
   fazer	
  análise	
  para	
  tornar	
  os	
  dados	
  buscáveis	
  mais	
  fáceis	
  de	
  
   serem	
  encontrados;	
  
EXPLAINing	
  	
  
mysql>	
  select	
  *	
  from	
  products	
  where	
  name	
  like	
  "%galacPca%";	
  
+-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+	
  
|	
  id	
  |	
  name	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  price	
  |	
  descripPon	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  category_id	
  |	
  
+-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+	
  
|	
  	
  2	
  |	
  Ba-lestar	
  GalacPca:	
  The	
  Complete	
  Series	
  |	
  39.90	
  |	
  All	
  four	
  seasons	
  in	
  a	
  single	
  pack	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  2	
  |	
  
|	
  	
  3	
  |	
  Ba-lestar	
  GalacPca:	
  The	
  Boardgame	
  	
  	
  	
  	
  	
  	
  |	
  59.90	
  |	
  A	
  game	
  of	
  strife,	
  space	
  fights	
  and	
  intrige	
  |	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  3	
  |	
  
+-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+	
  
2	
  rows	
  in	
  set	
  (0.00	
  sec)	
  

	
  
	
  
mysql>	
  explain	
  select	
  *	
  from	
  products	
  where	
  name	
  like	
  "%galacPca%";	
  
+-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+	
  
|	
  id	
  |	
  select_type	
  |	
  table	
  	
  	
  	
  |	
  type	
  |	
  possible_keys	
  |	
  key	
  	
  |	
  key_len	
  |	
  ref	
  	
  |	
  rows	
  |	
  Extra	
  	
  	
  	
  	
  	
  	
  |	
  
+-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+	
  
|	
  	
  1	
  |	
  SIMPLE	
  	
  	
  	
  	
  	
  |	
  products	
  |	
  ALL	
  	
  |	
  NULL	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  |	
  NULL	
  |	
  NULL	
  	
  	
  	
  |	
  NULL	
  |	
  	
  	
  12	
  |	
  Using	
  where	
  |	
  
+-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+	
  

	
  
	
  
Entram	
  as	
  ferramentas	
  de	
  
busca	
  textual	
  
•  Bancos	
  de	
  dados	
  não	
  servem,	
  surgem	
  as	
  ferramentas	
  de	
  
   busca	
  puramente	
  textual;	
  

•  Lucene,	
  escrita	
  em	
  Java,	
  torna-­‐se	
  a	
  ferramenta	
  open	
  source	
  
   mais	
  comum	
  pra	
  solucionar	
  esse	
  Ppo	
  de	
  problema;	
  

•  Surge	
  o	
  Solr,	
  um	
  servidor	
  web	
  com	
  interface	
  semi-­‐REST	
  para	
  
   que	
  outras	
  linguagens	
  possam	
  também	
  usar	
  o	
  Lucene	
  pra	
  
   busca	
  textual;	
  
Diferenças?	
  
•  Stemming	
  –	
  redução	
  das	
  palavras	
  para	
  o	
  seu	
  radical:	
  
   •  Cat	
  –	
  catlike,	
  ca-y,	
  catwoman,	
  caright	
  


•  Remoção	
  de	
  palavras	
  comuns:	
  
   •  e,	
  ou,	
  de,	
  aqui,	
  ali,	
  se,	
  a,	
  o,	
  	
  


•  Subdivisão	
  de	
  palavras:	
  
   •  PowerShot	
  DX3100	
  –	
  power,	
  shot,	
  dx,	
  3100	
  


•  Sinônimos	
  
   •  Casa	
  –	
  lar,	
  apartamento,	
  domicílio,	
  residência	
  
Lucene,	
  Solr	
  e	
  Rails	
  
•  Vários	
  plugins	
  disponíveis,	
  mas	
  só	
  o	
  Sunspot	
  (
   h-p://outowime.github.com/sunspot/	
  )	
  é	
  realmente	
  manPdo;	
  

•  Existe	
  um	
  port	
  do	
  Lucene	
  para	
  Ruby,	
  o	
  Ferret,	
  mas	
  está	
  sem	
  
   desenvolvimento	
  já	
  a	
  muito	
  tempo	
  e	
  é	
  instável	
  quando	
  várias	
  
   aplicações	
  usam	
  o	
  mesmo	
  índice;	
  

•  É	
  possível	
  usar	
  Lucene	
  diretamente	
  se	
  você	
  esPver	
  usando	
  
   JRuby;	
  
sunspot	
  e	
  sunspot_rails	
  
•  Gems	
  para	
  integrar	
  as	
  buscas	
  com	
  Solr	
  na	
  sua	
  aplicação,	
  
   contém	
  uma	
  instalação	
  do	
  Solr	
  como	
  servidor	
  web	
  pronto	
  pra	
  
   ser	
  uPlizado;	
  

•  Integram-­‐se	
  em	
  objetos	
  AcPveRecord,	
  mas	
  também	
  é	
  possível	
  
   usar	
  modelos	
  não	
  AcPveRecord;	
  

•  Projeto	
  em	
  movimento	
  constante	
  e	
  já	
  com	
  vários	
  plugins	
  pra	
  
   se	
  integrar	
  com	
  outros	
  bancos	
  de	
  dados,	
  como	
  MongoDB;	
  
Setup	
  –	
  conIig/sunspot.yml	
  
development:	
  
	
  	
  solr:	
  
	
  	
  	
  	
  hostname:	
  localhost	
  
	
  	
  	
  	
  port:	
  8980	
  
	
  	
  	
  	
  log_level:	
  DEBUG	
  
	
  	
  auto_commit_awer_request:	
  true	
  
	
  	
  	
  
test:	
  
	
  	
  solr:	
  
	
  	
  	
  	
  hostname:	
  localhost	
  
	
  	
  	
  	
  port:	
  8981	
  
	
  	
  	
  	
  log_level:	
  OFF	
  
	
  
producPon:	
  
	
  	
  solr:	
  
	
  	
  	
  	
  hostname:	
  localhost	
  
	
  	
  	
  	
  port:	
  8982	
  
	
  	
  	
  	
  log_level:	
  WARNING	
  
	
  	
  auto_commit_awer_request:	
  true	
  	
  
Setup	
  –	
  Parte	
  2	
  
•  Pegue	
  o	
  código	
  fonte	
  do	
  Sunspot	
  no	
  GitHub	
  -­‐	
  
   h-ps://github.com/outowime/sunspot	
  	
  

•  Copie	
  a	
  pasta	
  “sunspot/solr-­‐1.3/solr”	
  pra	
  dentro	
  do	
  seu	
  
   projeto	
  Rails	
  

•  Adicione	
  o	
  Sunspot	
  no	
  seu	
  Gemfile:	
  
	
  
        !gem 'sunspot',                                                 '1.2.1'!
        !gem 'sunspot_rails',                                           '1.2.1'!
Integrando	
  o	
  sunspot	
  em	
  um	
  
model	
  
class	
  Product	
  <	
  AcPveRecord::Base	
  
	
  	
  	
  
	
  	
  belongs_to	
  :category	
  
	
  	
  	
  
	
  	
  validates_presence_of	
  :name,	
  :descripPon,	
  :category_id,	
  :price	
  
	
  	
  validates_uniqueness_of	
  :name,	
  :allow_blank	
  =>	
  true	
  
	
  	
  	
  
	
  	
  searchable	
  :auto_index	
  =>	
  true,	
  :auto_remove	
  =>	
  true	
  do	
  
	
  	
  	
  	
  text	
  :name,	
  :boost	
  =>	
  2.0	
  
	
  	
  	
  	
  text	
  :descripPon	
  
	
  	
  	
  	
  float	
  :price	
  
	
  	
  	
  	
  integer	
  :category_id,	
  :references	
  =>	
  ::Category	
  
	
  	
  end	
  
	
  	
  	
  
	
  	
  def	
  to_s	
  
	
  	
  	
  	
  self.name	
  
	
  	
  end	
  
	
  	
  	
  
end	
  
E	
  no	
  controller	
  
class	
  ProductsController	
  <	
  ApplicaPonController	
  
	
  	
  
	
  	
  def	
  index	
  
	
  	
  	
  	
  @products	
  =	
  if	
  params[:q].blank?	
  
	
  	
  	
  	
  	
  	
  Product.all	
  :order	
  =>	
  'name	
  ASC'	
  
	
  	
  	
  	
  else	
  
	
  	
  	
  	
  	
  	
  Product.solr_search	
  do	
  |s|	
  
	
  	
  	
  	
  	
  	
  	
  	
  s.keywords	
  params[:q]	
  
	
  	
  	
  	
  	
  	
  end	
  
	
  	
  	
  	
  end	
  
	
  	
  end	
  
	
  	
  
end	
  
Mas	
  antes	
  de	
  continuar,	
  um	
  
pequeno	
  monkey-­‐patch	
  
::Sunspot::Search::StandardSearch.class_eval	
  do	
  
	
  	
  
	
  	
  include	
  Enumerable	
  
	
  	
  
	
  	
  delegate(	
  
	
  	
  	
  	
  :current_page,	
  
	
  	
  	
  	
  :per_page,	
  
	
  	
  	
  	
  :total_entries,	
  
	
  	
  	
  	
  :total_pages,	
  
	
  	
  	
  	
  :offset,	
  
	
  	
  	
  	
  :previous_page,	
  
	
  	
  	
  	
  :next_page,	
  
	
  	
  	
  	
  :out_of_bounds?,	
  
	
  	
  	
  	
  :each,	
  
	
  	
  	
  	
  :in_groups_of,	
  
	
  	
  	
  	
  :blank?,	
  
	
  	
  	
  	
  :[],	
  
	
  	
  	
  	
  :to	
  =>	
  :results)	
  
	
  	
  
end	
  
Na	
  sua	
  view	
  -­‐	
  1	
  
 %h1	
  Products	
  
 	
  
 %p=	
  link_to	
  'New	
  product',	
  new_product_path	
  
 	
  	
  	
  
 %h2	
  Search	
  products	
  
 	
  
 -­‐	
  form_tag	
  products_path,	
  :method	
  =>	
  :get	
  do	
  |t|	
  
 	
  	
  %p	
  
 	
  	
  	
  	
  =	
  text_field_tag	
  :q,	
  params[:q]	
  
 	
  	
  	
  	
  =	
  submit_tag	
  'Go!'	
  
 	
  	
  	
  	
  =	
  hidden_field_tag	
  :category_id,	
  params[:category_id]	
  
Na	
  sua	
  view	
  -­‐	
  2	
  
 =	
  will_paginate	
  @products	
  
 	
  	
  %table	
  
 	
  	
  	
  	
  %thead	
  
 	
  	
  	
  	
  	
  	
  %tr	
  
 	
  	
  	
  	
  	
  	
  	
  	
  %th	
  Name	
  
 	
  	
  	
  	
  	
  	
  	
  	
  %th	
  Category	
  
 	
  	
  	
  	
  	
  	
  	
  	
  %th	
  Price	
  
 	
  	
  	
  	
  %tbody	
  
 	
  	
  	
  	
  	
  	
  -­‐	
  for	
  product	
  in	
  @products	
  
 	
  	
  	
  	
  	
  	
  	
  	
  %tr	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  %td=	
  product	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  %td=	
  product.category	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  %td=	
  product.price	
  
 	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  %td=	
  link_to	
  'Edit',	
  edit_product_path(	
  product	
  )	
  
 	
  	
  =	
  will_paginate	
  @products	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
 -­‐	
  else	
  
 	
  	
  %p	
  There	
  are	
  no	
  products	
  available.	
  
Análise	
  de	
  dados	
  

•  Inicie	
  o	
  Solr	
  no	
  seu	
  projeto:	
  
    •  rake	
  sunspot:solr:run	
  



•  Faça	
  a	
  indexação	
  de	
  alguns	
  dos	
  seus	
  dados:	
  
    •  Product.solr_reindex	
  


•  Abra	
  a	
  administração	
  do	
  Solr:	
  
    •  h-p://localhost:8980/solr/admin/	
  
Snippet	
  -­‐	
  solr/conf/
schema.xml	
  
	
  
<fieldtype	
  class="solr.TextField"	
  posiPonIncrementGap="100"	
  
name="text">	
  
	
  	
  	
  	
  	
  	
  <analyzer>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <tokenizer	
  class="solr.StandardTokenizerFactory"/>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <filter	
  class="solr.StandardFilterFactory"/>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <filter	
  class="solr.LowerCaseFilterFactory"/>	
  
	
  	
  	
  	
  	
  	
  </analyzer>	
  
</fieldtype>	
  
Adicionando	
  mais	
  Iiltros	
  
<fieldtype	
  class="solr.TextField"	
  posiPonIncrementGap="100"	
  
name="text">	
  
	
  	
  <analyzer>	
  
	
  	
  	
  	
  <tokenizer	
  class="solr.StandardTokenizerFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.StandardFilterFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.LowerCaseFilterFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.StopFilterFactory"	
  words="stopwords.txt"	
  
ignoreCase="true"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.ISOLaPn1AccentFilterFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.TrimFilterFactory"	
  />	
  
	
  	
  </analyzer>	
  
</fieldtype>	
  
Buscas	
  com	
  match	
  parcial	
  
•  O	
  Lucene	
  normalmente	
  só	
  retorna	
  um	
  match	
  em	
  uma	
  palavra	
  
   se	
  ela	
  for	
  um	
  match	
  total	
  em	
  um	
  token,	
  ele	
  não	
  faz	
  matches	
  
   parciais	
  diretamente;	
  

•  Há	
  um	
  operador	
  pra	
  permiPr	
  o	
  match	
  parcial	
  de	
  palavras,	
  “*”,	
  
   mas	
  esse	
  operador	
  só	
  é	
  indicado	
  para	
  buscas	
  simples	
  em	
  
   índices	
  pequenos;	
  

•  Se	
  você	
  tem	
  um	
  índice	
  grande	
  e	
  precisa	
  de	
  performance	
  nas	
  
   suas	
  buscas,	
  precisa	
  usar	
  um	
  filtro	
  que	
  gere	
  pedaços	
  da	
  
   palavra	
  como	
  tokens	
  para	
  serem	
  buscados;	
  
Adicionando	
  o	
  ngram	
  Iilter	
  
<fieldtype	
  class="solr.TextField"	
  posiPonIncrementGap="100"	
  name="text">	
  
	
  	
  <analyzer	
  type="index">	
  
	
  	
  	
  	
  <tokenizer	
  class="solr.StandardTokenizerFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.StandardFilterFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.LowerCaseFilterFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.StopFilterFactory"	
  words="stopwords.txt"	
  ignoreCase="true"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.ISOLaPn1AccentFilterFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.TrimFilterFactory"	
  />	
  
	
  	
  	
  	
  <filter	
  class="solr.EdgeNGramFilterFactory"	
  
	
  	
  	
  	
  	
  	
  minGramSize="3"	
  
	
  	
  	
  	
  	
  	
  maxGramSize="30"/>	
  
	
  	
  </analyzer>	
  
	
  	
  <analyzer	
  type="query">	
  
	
  	
  	
  	
  <tokenizer	
  class="solr.StandardTokenizerFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.StandardFilterFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.LowerCaseFilterFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.StopFilterFactory"	
  words="stopwords.txt"	
  ignoreCase="true"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.ISOLaPn1AccentFilterFactory"/>	
  
	
  	
  	
  	
  <filter	
  class="solr.TrimFilterFactory"	
  />	
  
	
  	
  </analyzer>	
  
</fieldtype>	
  
Facets	
  
•  Facets	
  são	
  uma	
  forma	
  de	
  agrupar	
  os	
  resultados	
  com	
  base	
  em	
  
   um	
  dos	
  campos	
  do	
  seu	
  objeto	
  indexado;	
  

•  Você	
  poderia	
  retornar	
  os	
  produtos	
  do	
  resultado	
  da	
  busca	
  e	
  
   mostrar	
  para	
  o	
  usuário	
  quantos	
  produtos	
  em	
  cada	
  categoria	
  
   foram	
  retornados,	
  assim	
  o	
  usuário	
  poderia	
  filtrar	
  também	
  por	
  
   categoria;	
  
Adicionando	
  facets	
  na	
  busca	
  
	
  	
  	
  	
  	
  	
  result	
  =	
  Product.solr_search	
  do	
  |s|	
  
	
  	
  	
  	
  	
  	
  	
  	
  s.keywords	
  params[:q]	
  
	
  	
  	
  	
  	
  	
  	
  	
  unless	
  params[:category_id].blank?	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  s.with(	
  :category_id	
  ).equal_to(	
  params[:category_id].to_i	
  )	
  
	
  	
  	
  	
  	
  	
  	
  	
  else	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  s.facet	
  :category_id	
  
	
  	
  	
  	
  	
  	
  	
  	
  end	
  
	
  	
  	
  	
  	
  	
  	
  	
  s.paginate	
  :per_page	
  =>	
  3,	
  :page	
  =>	
  @page	
  
	
  	
  	
  	
  	
  	
  end	
  
	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  	
  	
  if	
  result.facet(	
  :category_id	
  )	
  
	
  	
  	
  	
  	
  	
  	
  	
  @facet_rows	
  =	
  result.facet(:category_id).rows	
  	
  	
  
	
  	
  	
  	
  	
  	
  end	
  
Na	
  sua	
  view	
  
	
  
-­‐	
  unless	
  @facet_rows.blank?	
  
	
  	
  %h3	
  Filters	
  
	
  	
  -­‐	
  %ul	
  
	
  	
  	
  	
  -­‐	
  @facet_rows.each	
  do	
  |facet|	
  
	
  	
  	
  	
  	
  	
  %li=	
  link_to(	
  "#{facet.instance}	
  (#{facet.count})",	
  
products_path(	
  :q	
  =>	
  params[:q],	
  :category_id	
  =>	
  
facet.instance	
  )	
  )	
  
Outras	
  ferramentas	
  de	
  busca	
  
textual	
  
•  Sphinx	
  -­‐	
  h-p://sphinxsearch.com/	
  



•  ElasPcSearch	
  -­‐	
  h-p://www.elasPcsearch.org/	
  



•  Ferret	
  -­‐	
  h-ps://github.com/dbalmain/ferret	
  	
  
DÚVIDAS?	
  

Más contenido relacionado

Similar a Busca textual com solr e sunspot no rails

Edição de conteúdo web usando Javascript de ponta a ponta
Edição de conteúdo web usando Javascript de ponta a pontaEdição de conteúdo web usando Javascript de ponta a ponta
Edição de conteúdo web usando Javascript de ponta a pontaJorge Walendowsky
 
Tutorial visão automação de testes e casper js
Tutorial visão automação de testes e casper jsTutorial visão automação de testes e casper js
Tutorial visão automação de testes e casper js4ALL Tests
 
Tutorial - Visão sobre Automação de Testes com CasperJS
Tutorial - Visão sobre Automação de Testes com CasperJSTutorial - Visão sobre Automação de Testes com CasperJS
Tutorial - Visão sobre Automação de Testes com CasperJSFrederico Allan
 
Coisas que aprendi e quero passar adiante - RubyConf Brasil 2010
Coisas que aprendi e quero passar adiante - RubyConf Brasil 2010Coisas que aprendi e quero passar adiante - RubyConf Brasil 2010
Coisas que aprendi e quero passar adiante - RubyConf Brasil 2010lucashungaro
 
SAPO Broker
SAPO BrokerSAPO Broker
SAPO Brokercodebits
 
don't repeat yourself front-ender
don't repeat yourself front-enderdon't repeat yourself front-ender
don't repeat yourself front-endertdc-globalcode
 
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )João Moura
 
Otimização Front-end para WordPress
Otimização Front-end para WordPressOtimização Front-end para WordPress
Otimização Front-end para WordPressGuga Alves
 
Ferramenta Flow - Análise estática de códigos javascript
Ferramenta Flow - Análise estática de códigos javascriptFerramenta Flow - Análise estática de códigos javascript
Ferramenta Flow - Análise estática de códigos javascriptRodrigo Ferreira
 
Spring MVC Framework
Spring MVC FrameworkSpring MVC Framework
Spring MVC Frameworkelliando dias
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmGuilherme Blanco
 
O que todos os developers devem saber sobre seo
O que todos os developers devem saber sobre seoO que todos os developers devem saber sobre seo
O que todos os developers devem saber sobre seointrofini
 
Cakephp - framework de desenvolvimento de aplicações Web em PHP
Cakephp - framework de desenvolvimento de aplicações Web em PHPCakephp - framework de desenvolvimento de aplicações Web em PHP
Cakephp - framework de desenvolvimento de aplicações Web em PHPArlindo Santos
 
Introduzindo StimulusJS: o novo Framework JavaScript para Ruby On Rails.
Introduzindo StimulusJS: o novo Framework JavaScript para Ruby On Rails.Introduzindo StimulusJS: o novo Framework JavaScript para Ruby On Rails.
Introduzindo StimulusJS: o novo Framework JavaScript para Ruby On Rails.Sergio Lima
 
Workshop Performance Rails
Workshop Performance RailsWorkshop Performance Rails
Workshop Performance RailsVitor Pellegrino
 
Coisas que eu gostaria de saber antes de começar a desenvolver temas e plugin...
Coisas que eu gostaria de saber antes de começar a desenvolver temas e plugin...Coisas que eu gostaria de saber antes de começar a desenvolver temas e plugin...
Coisas que eu gostaria de saber antes de começar a desenvolver temas e plugin...Leo Baiano
 
Javascript no SAPO e libsapojs
Javascript no SAPO e libsapojsJavascript no SAPO e libsapojs
Javascript no SAPO e libsapojscodebits
 

Similar a Busca textual com solr e sunspot no rails (20)

Edição de conteúdo web usando Javascript de ponta a ponta
Edição de conteúdo web usando Javascript de ponta a pontaEdição de conteúdo web usando Javascript de ponta a ponta
Edição de conteúdo web usando Javascript de ponta a ponta
 
Tutorial visão automação de testes e casper js
Tutorial visão automação de testes e casper jsTutorial visão automação de testes e casper js
Tutorial visão automação de testes e casper js
 
Tutorial - Visão sobre Automação de Testes com CasperJS
Tutorial - Visão sobre Automação de Testes com CasperJSTutorial - Visão sobre Automação de Testes com CasperJS
Tutorial - Visão sobre Automação de Testes com CasperJS
 
Coisas que aprendi e quero passar adiante - RubyConf Brasil 2010
Coisas que aprendi e quero passar adiante - RubyConf Brasil 2010Coisas que aprendi e quero passar adiante - RubyConf Brasil 2010
Coisas que aprendi e quero passar adiante - RubyConf Brasil 2010
 
SAPO Broker
SAPO BrokerSAPO Broker
SAPO Broker
 
don't repeat yourself front-ender
don't repeat yourself front-enderdon't repeat yourself front-ender
don't repeat yourself front-ender
 
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
WebSocket com Node.js ( socketstream && coffeescript ) X RoR ( Juggernaut )
 
Otimização Front-end para WordPress
Otimização Front-end para WordPressOtimização Front-end para WordPress
Otimização Front-end para WordPress
 
Ferramenta Flow - Análise estática de códigos javascript
Ferramenta Flow - Análise estática de códigos javascriptFerramenta Flow - Análise estática de códigos javascript
Ferramenta Flow - Análise estática de códigos javascript
 
Php 07 Cakephp
Php 07 CakephpPhp 07 Cakephp
Php 07 Cakephp
 
Spring MVC Framework
Spring MVC FrameworkSpring MVC Framework
Spring MVC Framework
 
Modern PHP
Modern PHPModern PHP
Modern PHP
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine Orm
 
O que todos os developers devem saber sobre seo
O que todos os developers devem saber sobre seoO que todos os developers devem saber sobre seo
O que todos os developers devem saber sobre seo
 
Cakephp - framework de desenvolvimento de aplicações Web em PHP
Cakephp - framework de desenvolvimento de aplicações Web em PHPCakephp - framework de desenvolvimento de aplicações Web em PHP
Cakephp - framework de desenvolvimento de aplicações Web em PHP
 
Arquitetura CSS
Arquitetura CSSArquitetura CSS
Arquitetura CSS
 
Introduzindo StimulusJS: o novo Framework JavaScript para Ruby On Rails.
Introduzindo StimulusJS: o novo Framework JavaScript para Ruby On Rails.Introduzindo StimulusJS: o novo Framework JavaScript para Ruby On Rails.
Introduzindo StimulusJS: o novo Framework JavaScript para Ruby On Rails.
 
Workshop Performance Rails
Workshop Performance RailsWorkshop Performance Rails
Workshop Performance Rails
 
Coisas que eu gostaria de saber antes de começar a desenvolver temas e plugin...
Coisas que eu gostaria de saber antes de começar a desenvolver temas e plugin...Coisas que eu gostaria de saber antes de começar a desenvolver temas e plugin...
Coisas que eu gostaria de saber antes de começar a desenvolver temas e plugin...
 
Javascript no SAPO e libsapojs
Javascript no SAPO e libsapojsJavascript no SAPO e libsapojs
Javascript no SAPO e libsapojs
 

Más de Maurício Linhares

Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDropUnindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDropMaurício Linhares
 
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDropMixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDropMaurício Linhares
 
Curso java 08 - mais sobre coleções
Curso java   08 - mais sobre coleçõesCurso java   08 - mais sobre coleções
Curso java 08 - mais sobre coleçõesMaurício Linhares
 
Curso java 06 - mais construtores, interfaces e polimorfismo
Curso java   06 - mais construtores, interfaces e polimorfismoCurso java   06 - mais construtores, interfaces e polimorfismo
Curso java 06 - mais construtores, interfaces e polimorfismoMaurício Linhares
 
Curso java 05 - herança, classes e métodos abstratos
Curso java   05 - herança, classes e métodos abstratosCurso java   05 - herança, classes e métodos abstratos
Curso java 05 - herança, classes e métodos abstratosMaurício Linhares
 
Curso java 04 - ap is e bibliotecas
Curso java   04 - ap is e bibliotecasCurso java   04 - ap is e bibliotecas
Curso java 04 - ap is e bibliotecasMaurício Linhares
 
Curso java 01 - molhando os pés com java
Curso java   01 - molhando os pés com javaCurso java   01 - molhando os pés com java
Curso java 01 - molhando os pés com javaMaurício Linhares
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetrosMaurício Linhares
 
Outsourcing e trabalho remoto para a nuvem
Outsourcing e trabalho remoto para a nuvemOutsourcing e trabalho remoto para a nuvem
Outsourcing e trabalho remoto para a nuvemMaurício Linhares
 
Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Maurício Linhares
 

Más de Maurício Linhares (20)

Mercado de TI
Mercado de TIMercado de TI
Mercado de TI
 
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDropUnindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
Unindo Ruby e Java através de uma arquitetura orientada a serviços na OfficeDrop
 
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDropMixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
Mixing Ruby and Java in a Service Oriented Architecture at OfficeDrop
 
Aprendendo ruby
Aprendendo rubyAprendendo ruby
Aprendendo ruby
 
Curso java 07 - exceções
Curso java   07 - exceçõesCurso java   07 - exceções
Curso java 07 - exceções
 
Curso java 08 - mais sobre coleções
Curso java   08 - mais sobre coleçõesCurso java   08 - mais sobre coleções
Curso java 08 - mais sobre coleções
 
Curso java 06 - mais construtores, interfaces e polimorfismo
Curso java   06 - mais construtores, interfaces e polimorfismoCurso java   06 - mais construtores, interfaces e polimorfismo
Curso java 06 - mais construtores, interfaces e polimorfismo
 
Curso java 05 - herança, classes e métodos abstratos
Curso java   05 - herança, classes e métodos abstratosCurso java   05 - herança, classes e métodos abstratos
Curso java 05 - herança, classes e métodos abstratos
 
Curso java 04 - ap is e bibliotecas
Curso java   04 - ap is e bibliotecasCurso java   04 - ap is e bibliotecas
Curso java 04 - ap is e bibliotecas
 
Curso java 01 - molhando os pés com java
Curso java   01 - molhando os pés com javaCurso java   01 - molhando os pés com java
Curso java 01 - molhando os pés com java
 
Curso java 02 - variáveis
Curso java   02 - variáveisCurso java   02 - variáveis
Curso java 02 - variáveis
 
Curso java 03 - métodos e parâmetros
Curso java   03 - métodos e parâmetrosCurso java   03 - métodos e parâmetros
Curso java 03 - métodos e parâmetros
 
Extreme programming
Extreme programmingExtreme programming
Extreme programming
 
Feature Driven Development
Feature Driven DevelopmentFeature Driven Development
Feature Driven Development
 
Migrando pra Scala
Migrando pra ScalaMigrando pra Scala
Migrando pra Scala
 
Outsourcing e trabalho remoto para a nuvem
Outsourcing e trabalho remoto para a nuvemOutsourcing e trabalho remoto para a nuvem
Outsourcing e trabalho remoto para a nuvem
 
Mercado hoje
Mercado hojeMercado hoje
Mercado hoje
 
Análise de sistemas oo 1
Análise de sistemas oo   1Análise de sistemas oo   1
Análise de sistemas oo 1
 
Revisão html e java script
Revisão html e java scriptRevisão html e java script
Revisão html e java script
 
Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010Aulas de Java Avançado 2- Faculdade iDez 2010
Aulas de Java Avançado 2- Faculdade iDez 2010
 

Último

ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx2m Assessoria
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsDanilo Pinotti
 
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx2m Assessoria
 
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx2m Assessoria
 
Programação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdfProgramação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdfSamaraLunas
 
Luís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdfLuís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdfLuisKitota
 
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docxATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx2m Assessoria
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploDanilo Pinotti
 
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docxATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx2m Assessoria
 

Último (9)

ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docxATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
ATIVIDADE 1 - GCOM - GESTÃO DA INFORMAÇÃO - 54_2024.docx
 
Boas práticas de programação com Object Calisthenics
Boas práticas de programação com Object CalisthenicsBoas práticas de programação com Object Calisthenics
Boas práticas de programação com Object Calisthenics
 
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docxATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
ATIVIDADE 1 - LOGÍSTICA EMPRESARIAL - 52_2024.docx
 
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docxATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
ATIVIDADE 1 - CUSTOS DE PRODUÇÃO - 52_2024.docx
 
Programação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdfProgramação Orientada a Objetos - 4 Pilares.pdf
Programação Orientada a Objetos - 4 Pilares.pdf
 
Luís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdfLuís Kitota AWS Discovery Day Ka Solution.pdf
Luís Kitota AWS Discovery Day Ka Solution.pdf
 
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docxATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
ATIVIDADE 1 - ESTRUTURA DE DADOS II - 52_2024.docx
 
Padrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemploPadrões de Projeto: Proxy e Command com exemplo
Padrões de Projeto: Proxy e Command com exemplo
 
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docxATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
ATIVIDADE 1 - SISTEMAS DISTRIBUÍDOS E REDES - 52_2024.docx
 

Busca textual com solr e sunspot no rails

  • 1. Busca  textual  com   Rais,  Solr  e  Sunspot   @mauriciojr  –  h-p://techbot.me/  
  • 2. Who?   •  Maurício  Linhares   •  @mauriciojr   •  h-p://techbot.me/   •  Developer  da  OfficeDrop.com   •  Professor  na  Faculdade  iDez   •  JUGleader  do  PBJUG  
  • 3. “LIKE”  considered  evil   •  Consultas  que  usam  LIKE  só  são  eficientes  se  a  coluna  esPver   indexada  e  for  uma  busca  de  prefixo:   •  “josé%”   •  “maria%”   •  Alguns  bancos  tem  um  limite  de  caracteres  que  podem  ser   indexado  em  campos  textuais;   •  Bancos  de  dados  relacionais  normalmente  não  são  capazes  de   fazer  análise  para  tornar  os  dados  buscáveis  mais  fáceis  de   serem  encontrados;  
  • 4. EXPLAINing     mysql>  select  *  from  products  where  name  like  "%galacPca%";   +-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+   |  id  |  name                                                                            |  price  |  descripPon                                                                |  category_id  |   +-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+   |    2  |  Ba-lestar  GalacPca:  The  Complete  Series  |  39.90  |  All  four  seasons  in  a  single  pack                    |                      2  |   |    3  |  Ba-lestar  GalacPca:  The  Boardgame              |  59.90  |  A  game  of  strife,  space  fights  and  intrige  |                      3  |   +-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+   2  rows  in  set  (0.00  sec)       mysql>  explain  select  *  from  products  where  name  like  "%galacPca%";   +-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+   |  id  |  select_type  |  table        |  type  |  possible_keys  |  key    |  key_len  |  ref    |  rows  |  Extra              |   +-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+   |    1  |  SIMPLE            |  products  |  ALL    |  NULL                    |  NULL  |  NULL        |  NULL  |      12  |  Using  where  |   +-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+      
  • 5. Entram  as  ferramentas  de   busca  textual   •  Bancos  de  dados  não  servem,  surgem  as  ferramentas  de   busca  puramente  textual;   •  Lucene,  escrita  em  Java,  torna-­‐se  a  ferramenta  open  source   mais  comum  pra  solucionar  esse  Ppo  de  problema;   •  Surge  o  Solr,  um  servidor  web  com  interface  semi-­‐REST  para   que  outras  linguagens  possam  também  usar  o  Lucene  pra   busca  textual;  
  • 6. Diferenças?   •  Stemming  –  redução  das  palavras  para  o  seu  radical:   •  Cat  –  catlike,  ca-y,  catwoman,  caright   •  Remoção  de  palavras  comuns:   •  e,  ou,  de,  aqui,  ali,  se,  a,  o,     •  Subdivisão  de  palavras:   •  PowerShot  DX3100  –  power,  shot,  dx,  3100   •  Sinônimos   •  Casa  –  lar,  apartamento,  domicílio,  residência  
  • 7. Lucene,  Solr  e  Rails   •  Vários  plugins  disponíveis,  mas  só  o  Sunspot  ( h-p://outowime.github.com/sunspot/  )  é  realmente  manPdo;   •  Existe  um  port  do  Lucene  para  Ruby,  o  Ferret,  mas  está  sem   desenvolvimento  já  a  muito  tempo  e  é  instável  quando  várias   aplicações  usam  o  mesmo  índice;   •  É  possível  usar  Lucene  diretamente  se  você  esPver  usando   JRuby;  
  • 8. sunspot  e  sunspot_rails   •  Gems  para  integrar  as  buscas  com  Solr  na  sua  aplicação,   contém  uma  instalação  do  Solr  como  servidor  web  pronto  pra   ser  uPlizado;   •  Integram-­‐se  em  objetos  AcPveRecord,  mas  também  é  possível   usar  modelos  não  AcPveRecord;   •  Projeto  em  movimento  constante  e  já  com  vários  plugins  pra   se  integrar  com  outros  bancos  de  dados,  como  MongoDB;  
  • 9. Setup  –  conIig/sunspot.yml   development:      solr:          hostname:  localhost          port:  8980          log_level:  DEBUG      auto_commit_awer_request:  true         test:      solr:          hostname:  localhost          port:  8981          log_level:  OFF     producPon:      solr:          hostname:  localhost          port:  8982          log_level:  WARNING      auto_commit_awer_request:  true    
  • 10. Setup  –  Parte  2   •  Pegue  o  código  fonte  do  Sunspot  no  GitHub  -­‐   h-ps://github.com/outowime/sunspot     •  Copie  a  pasta  “sunspot/solr-­‐1.3/solr”  pra  dentro  do  seu   projeto  Rails   •  Adicione  o  Sunspot  no  seu  Gemfile:     !gem 'sunspot', '1.2.1'! !gem 'sunspot_rails', '1.2.1'!
  • 11. Integrando  o  sunspot  em  um   model   class  Product  <  AcPveRecord::Base            belongs_to  :category            validates_presence_of  :name,  :descripPon,  :category_id,  :price      validates_uniqueness_of  :name,  :allow_blank  =>  true            searchable  :auto_index  =>  true,  :auto_remove  =>  true  do          text  :name,  :boost  =>  2.0          text  :descripPon          float  :price          integer  :category_id,  :references  =>  ::Category      end            def  to_s          self.name      end         end  
  • 12. E  no  controller   class  ProductsController  <  ApplicaPonController          def  index          @products  =  if  params[:q].blank?              Product.all  :order  =>  'name  ASC'          else              Product.solr_search  do  |s|                  s.keywords  params[:q]              end          end      end       end  
  • 13. Mas  antes  de  continuar,  um   pequeno  monkey-­‐patch   ::Sunspot::Search::StandardSearch.class_eval  do          include  Enumerable          delegate(          :current_page,          :per_page,          :total_entries,          :total_pages,          :offset,          :previous_page,          :next_page,          :out_of_bounds?,          :each,          :in_groups_of,          :blank?,          :[],          :to  =>  :results)       end  
  • 14. Na  sua  view  -­‐  1   %h1  Products     %p=  link_to  'New  product',  new_product_path         %h2  Search  products     -­‐  form_tag  products_path,  :method  =>  :get  do  |t|      %p          =  text_field_tag  :q,  params[:q]          =  submit_tag  'Go!'          =  hidden_field_tag  :category_id,  params[:category_id]  
  • 15. Na  sua  view  -­‐  2   =  will_paginate  @products      %table          %thead              %tr                  %th  Name                  %th  Category                  %th  Price          %tbody              -­‐  for  product  in  @products                  %tr                      %td=  product                      %td=  product.category                      %td=  product.price                      %td=  link_to  'Edit',  edit_product_path(  product  )      =  will_paginate  @products                       -­‐  else      %p  There  are  no  products  available.  
  • 16. Análise  de  dados   •  Inicie  o  Solr  no  seu  projeto:   •  rake  sunspot:solr:run   •  Faça  a  indexação  de  alguns  dos  seus  dados:   •  Product.solr_reindex   •  Abra  a  administração  do  Solr:   •  h-p://localhost:8980/solr/admin/  
  • 17. Snippet  -­‐  solr/conf/ schema.xml     <fieldtype  class="solr.TextField"  posiPonIncrementGap="100"   name="text">              <analyzer>                  <tokenizer  class="solr.StandardTokenizerFactory"/>                  <filter  class="solr.StandardFilterFactory"/>                  <filter  class="solr.LowerCaseFilterFactory"/>              </analyzer>   </fieldtype>  
  • 18. Adicionando  mais  Iiltros   <fieldtype  class="solr.TextField"  posiPonIncrementGap="100"   name="text">      <analyzer>          <tokenizer  class="solr.StandardTokenizerFactory"/>          <filter  class="solr.StandardFilterFactory"/>          <filter  class="solr.LowerCaseFilterFactory"/>          <filter  class="solr.StopFilterFactory"  words="stopwords.txt"   ignoreCase="true"/>          <filter  class="solr.ISOLaPn1AccentFilterFactory"/>          <filter  class="solr.TrimFilterFactory"  />      </analyzer>   </fieldtype>  
  • 19. Buscas  com  match  parcial   •  O  Lucene  normalmente  só  retorna  um  match  em  uma  palavra   se  ela  for  um  match  total  em  um  token,  ele  não  faz  matches   parciais  diretamente;   •  Há  um  operador  pra  permiPr  o  match  parcial  de  palavras,  “*”,   mas  esse  operador  só  é  indicado  para  buscas  simples  em   índices  pequenos;   •  Se  você  tem  um  índice  grande  e  precisa  de  performance  nas   suas  buscas,  precisa  usar  um  filtro  que  gere  pedaços  da   palavra  como  tokens  para  serem  buscados;  
  • 20. Adicionando  o  ngram  Iilter   <fieldtype  class="solr.TextField"  posiPonIncrementGap="100"  name="text">      <analyzer  type="index">          <tokenizer  class="solr.StandardTokenizerFactory"/>          <filter  class="solr.StandardFilterFactory"/>          <filter  class="solr.LowerCaseFilterFactory"/>          <filter  class="solr.StopFilterFactory"  words="stopwords.txt"  ignoreCase="true"/>          <filter  class="solr.ISOLaPn1AccentFilterFactory"/>          <filter  class="solr.TrimFilterFactory"  />          <filter  class="solr.EdgeNGramFilterFactory"              minGramSize="3"              maxGramSize="30"/>      </analyzer>      <analyzer  type="query">          <tokenizer  class="solr.StandardTokenizerFactory"/>          <filter  class="solr.StandardFilterFactory"/>          <filter  class="solr.LowerCaseFilterFactory"/>          <filter  class="solr.StopFilterFactory"  words="stopwords.txt"  ignoreCase="true"/>          <filter  class="solr.ISOLaPn1AccentFilterFactory"/>          <filter  class="solr.TrimFilterFactory"  />      </analyzer>   </fieldtype>  
  • 21. Facets   •  Facets  são  uma  forma  de  agrupar  os  resultados  com  base  em   um  dos  campos  do  seu  objeto  indexado;   •  Você  poderia  retornar  os  produtos  do  resultado  da  busca  e   mostrar  para  o  usuário  quantos  produtos  em  cada  categoria   foram  retornados,  assim  o  usuário  poderia  filtrar  também  por   categoria;  
  • 22. Adicionando  facets  na  busca              result  =  Product.solr_search  do  |s|                  s.keywords  params[:q]                  unless  params[:category_id].blank?                      s.with(  :category_id  ).equal_to(  params[:category_id].to_i  )                  else                      s.facet  :category_id                  end                  s.paginate  :per_page  =>  3,  :page  =>  @page              end                            if  result.facet(  :category_id  )                  @facet_rows  =  result.facet(:category_id).rows                  end  
  • 23. Na  sua  view     -­‐  unless  @facet_rows.blank?      %h3  Filters      -­‐  %ul          -­‐  @facet_rows.each  do  |facet|              %li=  link_to(  "#{facet.instance}  (#{facet.count})",   products_path(  :q  =>  params[:q],  :category_id  =>   facet.instance  )  )  
  • 24. Outras  ferramentas  de  busca   textual   •  Sphinx  -­‐  h-p://sphinxsearch.com/   •  ElasPcSearch  -­‐  h-p://www.elasPcsearch.org/   •  Ferret  -­‐  h-ps://github.com/dbalmain/ferret