Como implementar a funcionalidade de autocompletar com Elasticsearch

Como implementar a funcionalidade de autocompletar com Elasticsearch

A função de autocompletar presente na maioria das plataformas que utilizamos no dia a dia, como serviços de busca, plataformas de streaming e lojas online, já se provou uma excelente parceira no cotidiano daqueles que, assim como eu, utilizam a Internet diariamente.

Neste artigo veremos como implementar essa funcionalidade utilizando o Elasticsearch.

A partir da versão 7.2 é possível definir, no mapeamento do índice, campos do tipo search_as_you_type. O search_as_you_type é um tipo de dado de texto otimizado para soluções que utilizem o autocomplete.

PUT movies
{
  "mappings": {
    "properties": {
      "title": {
        "type": "search_as_you_type"
      }
    }
  }
}

Internamente, o Elasticsearch cria uma série de subcampos possibilitando consultas parciais no texto indexado. Para entendermos melhor, vamos inserir alguns documentos no índice movies:

PUT /movies/_bulk/
{"index":{}}
{"title":"Predestination","year":2014,"genre":["Action","Drama","Sci-Fi"]}
{"index":{}}
{"title":"Star Wars: Episode VII - The Force Awakens","year":2015,"genre":["Action","Adventure","Fantasy","Sci-Fi"]}
{"index":{}}
{"title":"Interstellar","year":2014,"genre":["Sci-Fi","Adventure","Drama"]}
{"index":{}}
{"title":"Venom","year":2018,"genre":["Action"," Adventure","Sci-Fi"]}
{"index":{}}
{"title":"A Quiet Place Part II","year":2020,"genre":["Horror","Sci-Fi","Drama"]}
{"index":{}}
{"title":"Donnie Darko","year":2001,"genre":["Drama","Sci-Fi","Mistery"]}
{"index":{}}
{"title":"Black Widow","year":2021,"genre":["Action"," Adventure","Sci-Fi"]}
{"index":{}}
{"title":"Nobody","year":2021,"genre":["Action","Drama","Crime"]}
{"index":{}}
{"title":"The Dark Knight","year":2008,"genre":["Action","Drama","Crime"]}
{"index":{}}
{"title":"Inception","year":2010,"genre":["Action"," Adventure","Sci-Fi"]}
{"index":{}}
{"title":"The Matrix","year":1999,"genre":["Action","Sci-Fi"]}
{"index":{}}
{"title":"Avatar","year":2009,"genre":["Action"," Adventure","Fantasy"]}
{"index":{}}
{"title":"Ex Machina","year":2014,"genre":["Action"," Adventure","Sci-Fi"]}
{"index":{}}
{"title":"The Hobbit: An Unexpected Journey","year":2012,"genre":[" Adventure","Fantasy"]}
{"index":{}}
{"title":"Wonder Woman","year":2017,"genre":["Action"," Adventure","Fantasy"]}
{"index":{}}
{"title":"Doctor Strange in the Multiverse of Madness","year":2022,"genre":["Action","Adventure","Fantasy"]}

Após a inserção, podemos utilizar a API analyze para testar o filtro do Elasticsearch e visualizar como seria indexado o título Star Wars:

POST movies/_analyze
{
    "tokenizer": "standard",
    "filter": [
        {
            "type": "edge_ngram",
            "min_gram": 2,
            "max_gram": 4
        }
    ],
    "text": "Star Wars"
}

No resultado podemos visualizar tokens do texto informado, é dessa forma que o Elasticsearch prepara os dados indexados fornecendo a informação pronta para ser analisada.

{
  "tokens": [
    {
      "token": "St",
      "start_offset": 0,
      "end_offset": 4,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "Sta",
      "start_offset": 0,
      "end_offset": 4,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "Star",
      "start_offset": 0,
      "end_offset": 4,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "Wa",
      "start_offset": 5,
      "end_offset": 9,
      "type": "<ALPHANUM>",
      "position": 1
    },
    ...
    ...
    ...
  ]
}

Para testarmos de fato a utilização do autocomplete, vamos utilizar um script escrito em shell que basicamente captura o que digitamos e envia uma solicitação de consulta ao Elasticsearch a cada caracter informado:

INPUT=''
printf "Digite o título do filme:\n"

while true; do IFS= read -rsn1 char; INPUT=$INPUT$char; echo $INPUT; curl --silent --request GET 'http://127.0.0.1:9200/movies/_search' \
 --header 'Content-Type: application/json' \
 --data-raw '{
     "size": 7,
     "query": {
         "multi_match": {
             "query": "'"$INPUT"'",
             "type": "bool_prefix",
             "fields": [
                 "title",
                 "title._2gram",
                 "title._3gram"
             ]
         }
     }
 }' | jq .hits.hits[]._source.title|grep -i --color "$INPUT"; echo "------------------------------"; done

Para a utilização do script, a ferramenta jq deve ser instalada.

Podemos validar a solução executando o script:

Essa é apenas uma das formas de implementar o autocomplete utilizando o Elasticsearch. Apesar de não requerer muita configuração e funcionar bem para a maioria dos casos, vimos que ele prepara os dados previamente através de tokens, o que torna a consulta bastante rápida. Porém, esse tipo de abordagem aumenta significativamente o tamanho do índice, já que a mesma informação é indexada diversas vezes.

Líder em Treinamento e serviços de Consultoria, Suporte e Implantação para o mundo open source. Conheça nossas soluções:

CURSOSCONSULTORIA

 

Anterior Guia Rápido: Como Fazer Deploy de uma API Python na Cloud Usando Containers
Próxima Crie sua própria Wiki: Guia passo a passo para instalação e uso

About author

Você pode gostar também

Infraestrutura TI

Piwik: A alternativa open source ao Google Analytics para análise de métricas

Não, o Piwik não é uma fruta derivada do Kiwi, é uma solução de Web Analytics open source, madura e eficiente para análise de métricas sobre audiência em sites e

Infraestrutura TI

12 Práticas Eficazes para Combater Ataques DDoS em Seu Servidor

Muito bem… como primeiro post por aqui… eu pensei em abordar um assunto que constantemente me abordam nos treinamentos e palestras e bate papos que tenho, que e sobre ataque

DevOps

Guia completo para instalação do Gitea: Ferramenta open source de gerenciamento de código-fonte

O Gitea é uma ferramenta open source de Source Code Management – SCM, ou seja, gerenciamento de código-fonte, escrita em Go e que foi criada em novembro de 2016 além