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

Containers

Gerenciamento eficiente de infraestrutura Docker com Portainer.io

O gerenciamento de uma infraestrutura com docker se dá quase que exclusivamente via terminal, mas quando surge a necessidade de apresentar a infraestrutura para a equipe, ou para toda a

Cloud

Descubra o Jitsi: a solução completa para videoconferências

Logo do Jitsi Introdução Durante o momento que vivemos, basicamente todas nossas interações se tornaram virtuais, com o home office sendo a alternativa primaria para muitas empresas, tivemos um súbito

Infraestrutura TI

Proteja seu e-mail contra spam e vírus com ferramentas open source

Um dos maiores ou até mesmo o maior problema quando falamos de e-mail é o recebimento de spam e vírus, um incomodo enorme tanto para o cliente final como a