Como fazer pesquisas (inteligentes) usando Ruby On Rails + ElasticSearch

elastic search
Para que Serve? Atende a sua necessidade? ūüôā

Muitos tipos de aplicativos precisam de um sistema de busca de resultados como por exemplo o Airbnb para encontrar casas, o Tinder para encontrar um pretendente, o Google para encontrar a página que você busca e etc.

Existem muitas maneiras de fazer esse tipo de busca dentro do Rails e o mais comum de se ver em Apps pequenos s√£o pesquisas direto no banco de dados usando “where” (ou “query sql”). Esse m√©todo funciona, mas tem um baixo desempenho quando voc√™ precisa fazer dezenas (centenas ou milhares) de pesquisas por minuto e ele tamb√©m precisa de muitas adapta√ß√Ķes para remover acentos, aceitar palavras parecidas, etc.

Uma op√ß√£o muito boa para evitar fazer na “m√£o” todo esse tratamento e ainda ter uma performance excelente √© usar o ElasticSearch que √© um servidor de buscas baseado no Apache Lucene. Ele consegue fazer buscas inteligentes encontrando os resultados mesmo que o usu√°rio erre a acentua√ß√£o, escreva palavras separas juntas (como por exemplo “the beatles” sendo escrito “TheBeatles”) e etc.

Ent√£o vamos l√°, vamos ver como integrar ele com o Rails e criar sua busca inteligente.

O que vamos aprender?

Como criar um App usando Ruby On Rails que pode se comunicar com o ElasticSearch e fazer buscas inteligentes para encontrar resultados baseados em keywords digitadas pelo usu√°rio. Mais especificamente, n√≥s vamos criar um App para o usu√°rio digitar palavras chaves e encontrar alguns Seriados que possuam essas palavras digitadas, como por exemplo “Marvel”, “Suspense” e etc.

INGREDIENTES
Objetivos (Passo a Passo)
  1. Criar o projeto e configurar a base para a pesquisa
  2. Criar uma interface gr√°fica para o usu√°rio poder realizar a pesquisa
  3. Incluir a busca no App
Mãos à Obra \o/
Criar o projeto e configurar a base para a pesquisa

Nessa etapa nós vamos criar o projeto, instalar as Gems, criar nosso Model e Controller Series e instalar o ElasticSearch, vamos lá:

  1. Vamos criar o nosso projeto usando a ajuda do Rails Composer que é uma ferramenta que te ajuda a criar o projeto com as principais bibliotecas já instaladas (te permitindo escolher direto no shell quais Gems você deseja), rode:
    1
    
    rails new search -m https://raw.github.com/RailsApps/rails-composer/master/composer.rb

    *No shell ele vai te questionar sobre quais Gems ou servi√ßos voc√™ quer que venham pr√© instaladas, na primeira op√ß√£o escolha o numero 3 (Custom application (experimental)), nas pr√≥ximas perguntas escolha sempre a op√ß√£o numero 1 at√© que ele te pergunte sobre o¬†Front-end framework, nessa pergunta voc√™ deve escolher a op√ß√£o numero 3 (Bootstrap 3.3) e novamente em todas as outras op√ß√Ķes escolha a op√ß√£o numero 1 ou N.
    (Foi um sufoco tantas op√ß√Ķes, mas pelo menos agora voc√™ conhece o Rails Composer \o/ )

  2. Coloque o elastickick no seu Gemfile:
    1
    
    gem 'searchkick'
  3. Vamos rodar o bundle para instalar a gem:
    1
    
    bundle
  4. Crie o Model Series com os campos name, description e link (para armazenarmos as series que vamos pesquisar):
    1
    
    rails g model Series name:string description:text link:string
  5. Crie agora o Controller Series para podermos fazer a pesquisa
    1
    
    rails g controller Series index
  6. Agora vamos configurar nossas rotas para o Series Index estar no root, no seu routes.rb coloque:
    1
    
    root to: "series#index"
  7. Rode no seu console o comando para criar o banco de dados e rodar as migrations que criamos junto com o Model Series:
    1
    
    rake db:create & rake db:migrate
  8. Rode o servidor
    1
    
    rails s
  9. Veja seu projeto no browser acessando http://localhost:3000/
  10. Agora para finalizar essa etapa, vamos instalar o ElastichSearch no linux (caso você esteja no mac ou windows acesse:  https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html)
    1. Primeiro instale o Java (√Č uma depend√™ncia do ElasticSearch):
      1
      
      sudo apt-get install default-jdk
    2. Agora baixe o elasticsearch:
      1
      
      wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.0.0.deb
    3. Instale o pacote:
      1
      
      sudo dpkg -i elasticsearch-5.0.0.deb
    4. Vamos dar o start no ElasticSearch, primeiro rode:
      1
      
      ps -p 1

      Caso o resultado seja como a baixo “systemd”:
      captura-de-tela-de-2016-11-05-00-16-01Ent√£o rode:

      1
      
      sudo systemctl start elasticsearch.service

      Caso o resultado seja “init”, rode

      1
      
      sudo -i service elasticsearch start
    5. Vamos testar para ver se o Elasticsearch est√° funcionando corretamente:
      1
      
      curl -X GET 'http://localhost:9200'

      captura-de-tela-de-2016-11-04-23-07-39
      *O ElasticSearch pode ser um pouco ‘chato’ de instalar, caso voc√™ n√£o receba um json como resultado, d√™ uma olhada nesse link da documenta√ß√£o oficial de instala√ß√£o:¬†https://www.elastic.co/guide/en/elasticsearch/reference/current/deb.html
      Outras configura√ß√Ķes para deixar o ElasticSearch mais seguro e aumentar a performance podem ser encontrados em:¬†https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-elasticsearch-on-ubuntu-16-04

  11. Pronto \o/ vencemos a primeira etapa, agora √© s√≥ alegria ūüôā
Criar uma interface gr√°fica para o usu√°rio poder realizar a pesquisa

Agora nós vamos criar a View para que o nosso usuário posso realizar as pesquisas e também vamos entrar com alguns dados de teste no banco de dados para que nós possamos mostrar nossos resultados iniciais.

  1. Eu criei previamente um modelo de Html bem simples usando Bootstrap para a página de Pesquisa para podermos manter o foco apenas no fluxo da pesquisa, então para simplificar copie o código a baixo no arquivo /app/views/series/index.html.erb:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    <div class="container">
      <form role="form" action="/">
        <h2 class="">Encontrando Séries</h2>
        <input type="text" class="form-control" placeholder="Ex: Marvel" name="keywords">
        <br>
        <button class="btn btn-primary btn-block" type="submit">Procurar</button>
        <br>
      </form>
      <section class="series">
        <% if @series.present? %>
          <% @series.each do |serie| %>
            <div class="col-md-12">
              <h1><%= serie.name %></h1>
              <p><%= serie.description %></p>
              <p><a href="<%= serie.link %>">Veja mais clicando aqui</a></p>
            </div>
          <% end %>
        <% end %>
      </selection>
    </div>
  2. Agora vamos inserir algumas series no banco de dados, rode no console:
    1
    
    rails c
  3. Agora rode todos esses comandos no console do rails:
    1
    
    Series.create name: 'The Black List', description: 'Raymond Reddington, um dos criminosos mais procurados pelo FBI, entrega-se às autoridades. Promete entregar diversos criminosos e terroristas desde que trate somente com Elizabeth Keen, uma funcionária novata do FBI. Aparentemente não há ligação entre eles e ele também não revela o motivo dessa preferência', link: 'https://pt.wikipedia.org/wiki/The_Blacklist'

     

    1
    
    Series.create name: 'The Big Bang Theory', description: 'The Big Bang Theory (Big Bang: A Teoria (título no Brasil) ou A Teoria do Big Bang (título em Portugal)), frequentemente abreviada como "TBBT", é uma série de televisão norte-americana de comédia de situação criada por Chuck Lorre e Bill Prady, que estreou no canal CBS em 22 de setembro de 2007', link: 'https://pt.wikipedia.org/wiki/The_Big_Bang_Theory'

     

    1
    
    Series.create name: 'Orphan Black', description: 'Orphan Black √© uma s√©rie de televis√£o canadense de fic√ß√£o cient√≠fica, criada por Graeme Manson e John Fawcett, estrelada por Tatiana Maslany como v√°rias pessoas id√™nticas que s√£o clones. A s√©rie centra-se em Sarah Manning, uma mulher que assume a identidade de outro clone, Elizabeth Childs, depois de testemunhar o suic√≠dio da mesma. A s√©rie levanta quest√Ķes sobre as implica√ß√Ķes morais e √©ticas da clonagem humana e seus efeitos sobre quest√Ķes de identidade pessoal', link: 'https://pt.wikipedia.org/wiki/Orphan_Black'

     

    1
    
    Series.create name: 'Luke Cage', description: 'Luke Cage, anteriormente conhecido como Poderoso (no original Powerman), é um super-herói de histórias em quadrinhos da Marvel Comics. Nascido nas ruas do Harlem, ex-membro de gangue, foi preso por um crime que não cometeu. Voluntário em uma experiência científica, foi vítima de sabotagem de um carcereiro. Acabou ganhando superforça e pele invulnerável. Fora da cadeia, passou a trabalhar por dinheiro, geralmente como guarda-costas, e participou de aventuras ao lado de vários outros heróis, principalmente Demolidor e Punho de Ferro. A série foi cancelada no final dos anos 1980 e ele passou a ser usado apenas como coadjuvante em HQs de outros personagens. No ano 2001, estreou nova série, agora pelo selo Marvel MAX. Também foi personagem regular da série The Pulse que, assim como Alias, foi estrelada por sua atual esposa, Jessica Jones', link: 'https://pt.wikipedia.org/wiki/Luke_Cage'

     

    1
    
    Series.create name: 'Agent Carter', description: 'Marvels Agent Carter ou simplesmente Agent Carter, foi uma série de televisão americana criada por Christopher Markus e Stephen McFeely, transmitida pela ABC. A série se passa depois dos eventos vistos em Capitão América: O Primeiro Vingador, acompanhando Peggy Carter conforme ela lida com o desaparecimento de Steve Rogers e o novo emprego na RCE (Reserva Científica e Estratégica)', link: 'https://pt.wikipedia.org/wiki/Agent_Carter'

     

  4. Rode o projeto e dê uma olhada no resultado:
    1
    
    rails s

    O resultado deve ser o mesmo que abaixo:
    captura-de-tela-de-2016-11-04-22-05-48

  5. Parabéns, passamos mais uma fase \o/ rumo ao sucesso.
Incluir a busca no App

Nesta parte de conclus√£o do tutorial n√≥s vamos finalmente conectar o nosso App ao ElasticSearch e realizar algumas buscas. Primeiro n√≥s precisamos “criar” o banco de dados no ElasticSearch, e a cada nova inclus√£o de dados no nosso banco automaticamente n√≥s vamos alimentar tamb√©m o banco de dados do ElasticSearch.

  1. Para começar vamos adicionar o Elastichkick ao nosso Model Series, em /app/models/series.rb substitua por:
    1
    2
    3
    
    class Series < ApplicationRecord
      searchkick
    end
  2. Agora vamos criar o banco no ElasticSearch, rode os seguintes comandos:
    1. Primeiro
      1
      
      rails c
    2. E agora para criar o banco associado ao model rode:
      1
      
      Series.reindex

      reindex

  3. No nosso controller Series, vamos colocar o comando para pesquisar nos campos name e description a frase que digitarmos no campo de busca, em /app/controllers/series_controller.rb substitua por:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    class SeriesController < ApplicationController
      def index
        # Verifica se o usu√°rio entrou com keywords
        if params[:keywords].present?
          # Diz ao elastickick para pesquisar as keyrwords nos campos name e description
          @series = Series.search params[:keywords], fields: [:name, :description]
        end
      end
    end
  4. Excelente, agora nós já estamos prontos, rode o servidor:
    1
    
    rails s
  5. V√° at√© o console e fa√ßa suas buscas http://localhost:3000, perceba que voc√™ pode colocar acentua√ß√Ķes incorretas ou at√© mesmo separar incorretamente as palavras e mesmo assim ele vai encontrar os resultados corretos.
    Existem muitas op√ß√Ķes para voc√™ configurar suas pesquisas, veja as principais clicando nesse link¬†https://github.com/ankane/searchkick
    captura-de-tela-de-2016-11-04-22-21-52
  6. Parabéns nós conseguimos fazer um sistema de buscas conectando o Rails e o Elastichsearch \o/.
CONCLUSÃO

Usar o ElasticSearch através do Searchkick é bem simples e vai te dar um meio de fazer pesquisas de nível profissional. Então se você precisa deste tipo de função este pode ser o caminho para você.

Como de costume o Código completo da aplicação está no Github, caso você queria clonar o código, clique aqui. Aproveita e me segue lá \o/

Apenas fazendo um merchandising do bem, uma empresa que eu participo √© o NegocieApp.com, um site para enviar propostas comerciais (Mandar or√ßamentos e etc para clientes) onde voc√™ e a sua equipe podem negociar com o cliente pela plataforma e ter um relat√≥rio sobre o numero de sucessos nas negocia√ß√Ķes e etc, √© bem bacana, d√° uma olhada l√° ūüôā
banner-cta

Se voc√™ ficou com d√ļvidas ou tem sugest√Ķes de posts para o Blog comenta a√≠ em baixo ou me adiciona no Facebook clicando aqui.

Muito Obrigado,
Sua presença aqui é uma honra para mim,
Leonardo Scorza ūüôā

Deixe seu Feedback!

Coment√°rios