Skip to content

11 ‐ Search

inhogoes edited this page May 21, 2026 · 8 revisions

11.1 - O quarto pilar: Elasticsearch como plataforma de busca com IA

O Elastic Stack é frequentemente descrito como tendo três soluções principais: Observabilidade, Segurança e Search. As duas primeiras já foram abordadas nos capítulos anteriores. Este capítulo cobre o terceiro pilar — a plataforma de busca — com foco nas funcionalidades de inteligência artificial que o Elasticsearch 9.x introduziu como recursos nativos.

A evolução do Elasticsearch ao longo dos anos seguiu uma trajetória clara:

Busca por palavras-chave (BM25)
        ↓
Busca vetorial densa (kNN)
        ↓
Busca semântica (ELSER / sparse vectors)
        ↓
Busca híbrida (BM25 + semântico com RRF)
        ↓
RAG — Retrieval Augmented Generation (busca + LLM)

Cada camada adicionou capacidade sem substituir a anterior. Em 2026, uma implementação de busca moderna usa todas essas camadas em conjunto.


11.2 - Conceitos fundamentais de busca com IA

BM25 — a base da busca por palavras-chave

O BM25 (Best Match 25) é o algoritmo de ranking padrão do Elasticsearch desde a versão 5.x. Ele calcula a relevância de um documento para uma query com base em dois fatores: a frequência do termo no documento (TF) e a raridade do termo no índice como um todo (IDF). Documentos que contêm termos raros e relevantes recebem score mais alto.

Limitação: o BM25 só encontra o que está escrito. Se você buscar por "problema de conexão", ele não vai encontrar documentos que falam em "falha de rede" ou "timeout" — a menos que essas palavras estejam presentes.

Busca vetorial — representando significado como números

Modelos de linguagem (como BERT, E5 e outros) transformam texto em vetores numéricos — listas de números de alta dimensão onde textos com significado similar ficam próximos no espaço vetorial. Isso permite encontrar documentos por proximidade semântica, não por correspondência de palavras.

"problema de conexão"     → [0.23, -0.41, 0.87, ...]
"falha de rede"           → [0.21, -0.39, 0.85, ...]  ← próximos no espaço vetorial
"receita de bolo"         → [-0.92, 0.11, -0.34, ...] ← distantes

O Elasticsearch armazena esses vetores em campos do tipo dense_vector e usa algoritmos de busca aproximada (HNSW) para encontrar os vetores mais próximos de forma eficiente.

ELSER — o modelo de busca semântica da Elastic

O ELSER (Elastic Learned Sparse EncodeR) é o modelo de busca semântica desenvolvido pela Elastic. Diferente dos modelos de dense vector, o ELSER usa sparse vectors — em vez de um vetor denso com centenas de dimensões, ele expande o texto em termos associados com seus pesos de relevância.

"problema de conexão" → { "rede": 0.82, "falha": 0.71, "timeout": 0.65, "conectividade": 0.58, ... }

Vantagens do ELSER em relação a dense vectors:

  • Não requer fine-tuning — funciona out-of-the-box com qualquer domínio de dados
  • Mais eficiente em armazenamento e busca que dense vectors de alta dimensão
  • Recomendado para documentos e queries em inglês
  • Para outros idiomas, a Elastic recomenda o modelo E5 (multilingual)

semantic_text — o campo que simplifica tudo

Introduzido no Elasticsearch 8.15 e GA no 9.x, o tipo de campo semantic_text é a forma mais simples de adicionar busca semântica a um índice. Você declara o campo como semantic_text, associa a um modelo de inferência, e o Elasticsearch cuida de gerar os embeddings automaticamente na indexação e na busca — sem precisar configurar pipelines de ingestão ou queries especiais.

Hybrid Search — o melhor dos dois mundos

A busca híbrida combina BM25 e busca semântica em um único resultado, usando um algoritmo de fusão chamado RRF (Reciprocal Rank Fusion). O RRF pondera os rankings de cada abordagem e produz um resultado final que se beneficia tanto da precisão das palavras-chave quanto do entendimento semântico.

GET /meu-indice/_search
{
  "retriever": {
    "rrf": {
      "retrievers": [
        { "standard": { "query": { "match": { "texto": "problema de conexão" } } } },
        { "standard": { "query": { "semantic": { "field": "texto_semantico", "query": "problema de conexão" } } } }
      ]
    }
  }
}

RAG — Retrieval Augmented Generation

RAG é uma arquitetura que combina um sistema de busca (como o Elasticsearch) com um modelo de linguagem (LLM). Em vez de responder uma pergunta só com o conhecimento interno do LLM — que pode estar desatualizado ou não ter acesso a dados privados —, o sistema primeiro busca os documentos mais relevantes no Elasticsearch e os passa como contexto para o LLM gerar a resposta.

Pergunta do usuário
        ↓
Elasticsearch busca os documentos mais relevantes
        ↓
Documentos + Pergunta → LLM
        ↓
Resposta gerada com base nos seus dados

O benefício: o LLM responde com base nos seus dados reais, não nos dados de treinamento. Isso reduz alucinações e permite que o sistema responda perguntas sobre informações privadas ou recentes que o LLM não conhece.


11.3 - Reindexação com _reindex

Antes de entrar nos labs de busca semântica, é importante entender o _reindex — uma operação que você vai usar com frequência ao adicionar novas capacidades a índices existentes.

O _reindex copia documentos de um índice de origem para um índice de destino, aplicando qualquer transformação configurada (como um pipeline de ingestão). É a operação padrão para:

  • Mudar o mapping de um índice (ex: adicionar um campo semantic_text)
  • Aplicar uma pipeline de ingestão a dados já existentes
  • Migrar dados para uma nova estrutura de índice
POST /_reindex
{
  "source": {
    "index": "indice-original"
  },
  "dest": {
    "index": "indice-novo",
    "pipeline": "minha-pipeline"
  }
}

Acompanhar o progresso:

GET /_tasks?actions=*reindex&detailed=true

Nota: o _reindex não é instantâneo em índices grandes. Em produção, execute sempre com wait_for_completion: false e monitore o progresso via _tasks.


11.4 - Laboratório 1: busca semântica com ELSER e semantic_text

Neste laboratório vamos ativar a licença trial, configurar o ELSER via Elastic Inference Service (EIS), criar um índice com o campo semantic_text e comparar resultados de busca por palavras-chave vs. busca semântica.

Pré-requisito: este lab requer licença Enterprise ou Trial ativa. O ELSER via EIS também requer que o cluster tenha um node com o role ml.


Passo 1 — Ativar a licença trial

Se o cluster estiver na licença Basic, ative o trial de 30 dias:

POST /_license/start_trial?acknowledge=true

Verifique que o trial está ativo:

GET /_license

O campo type deve mostrar trial e status deve mostrar active.


Passo 2 — Verificar o endpoint de inferência do ELSER

O ELSER está disponível no Elastic Inference Service (EIS) como endpoint pré-configurado. Verifique se está disponível:

GET /_inference

Procure pelo endpoint .elser-2-elastic na resposta. Se estiver presente, o EIS está ativo e pronto para uso.

Se não estiver disponível no cluster local, use o endpoint alternativo via ML node:

PUT /_inference/sparse_embedding/.elser-2
{
  "service": "elser",
  "service_settings": {
    "num_allocations": 1,
    "num_threads": 1
  }
}

Aguarde o modelo ser carregado. Pode levar alguns minutos na primeira vez — o Elasticsearch vai baixar e inicializar o modelo no node ML.

Verifique que o modelo está pronto:

GET /_inference/.elser-2

Passo 3 — Criar o índice com semantic_text

O campo semantic_text cuida de tudo automaticamente: gera os embeddings na indexação e executa a busca semântica quando você usa a query semantic.

PUT /artigos-tecnologia
{
  "mappings": {
    "properties": {
      "titulo":   { "type": "text" },
      "conteudo": { "type": "text" },
      "conteudo_semantico": {
        "type": "semantic_text",
        "inference_id": ".elser-2-elastic"
      }
    }
  }
}

Se estiver usando o endpoint alternativo do passo 2, substitua .elser-2-elastic por .elser-2.


Passo 4 — Indexar documentos

POST /_bulk
{ "index": { "_index": "artigos-tecnologia", "_id": "1" } }
{ "titulo": "Problemas de conectividade em redes corporativas", "conteudo": "Falhas de rede podem ocorrer por diversos motivos: timeout de conexão, roteamento incorreto, firewall bloqueando portas, ou sobrecarga do servidor DNS. O diagnóstico começa pela verificação da camada física e sobe até a camada de aplicação.", "conteudo_semantico": "Falhas de rede podem ocorrer por diversos motivos: timeout de conexão, roteamento incorreto, firewall bloqueando portas, ou sobrecarga do servidor DNS. O diagnóstico começa pela verificação da camada física e sobe até a camada de aplicação." }
{ "index": { "_index": "artigos-tecnologia", "_id": "2" } }
{ "titulo": "Otimização de queries em bancos de dados relacionais", "conteudo": "Queries lentas em bancos de dados geralmente são causadas por falta de índices, planos de execução ineficientes, ou excesso de JOINs. O uso de EXPLAIN ANALYZE revela o custo de cada operação e indica onde otimizar.", "conteudo_semantico": "Queries lentas em bancos de dados geralmente são causadas por falta de índices, planos de execução ineficientes, ou excesso de JOINs. O uso de EXPLAIN ANALYZE revela o custo de cada operação e indica onde otimizar." }
{ "index": { "_index": "artigos-tecnologia", "_id": "3" } }
{ "titulo": "Kubernetes: escalabilidade automática de pods", "conteudo": "O Horizontal Pod Autoscaler (HPA) escala automaticamente o número de pods com base em métricas de CPU, memória ou métricas customizadas. A configuração envolve definir o número mínimo e máximo de réplicas e o threshold de utilização.", "conteudo_semantico": "O Horizontal Pod Autoscaler (HPA) escala automaticamente o número de pods com base em métricas de CPU, memória ou métricas customizadas. A configuração envolve definir o número mínimo e máximo de réplicas e o threshold de utilização." }
{ "index": { "_index": "artigos-tecnologia", "_id": "4" } }
{ "titulo": "Segurança em APIs REST: autenticação e autorização", "conteudo": "APIs REST devem implementar autenticação via tokens JWT ou OAuth 2.0. A autorização é feita verificando as permissões do token antes de executar cada operação. Ataques comuns incluem injection, broken authentication e excessive data exposure.", "conteudo_semantico": "APIs REST devem implementar autenticação via tokens JWT ou OAuth 2.0. A autorização é feita verificando as permissões do token antes de executar cada operação. Ataques comuns incluem injection, broken authentication e excessive data exposure." }
{ "index": { "_index": "artigos-tecnologia", "_id": "5" } }
{ "titulo": "Monitoramento de aplicações com métricas e alertas", "conteudo": "O monitoramento eficaz combina métricas de sistema (CPU, memória, disco) com métricas de aplicação (latência, taxa de erros, throughput). Alertas devem ser configurados com thresholds dinâmicos para evitar ruído.", "conteudo_semantico": "O monitoramento eficaz combina métricas de sistema (CPU, memória, disco) com métricas de aplicação (latência, taxa de erros, throughput). Alertas devem ser configurados com thresholds dinâmicos para evitar ruído." }

O Elasticsearch vai processar os campos conteudo_semantico em background usando o ELSER. Aguarde alguns segundos antes de executar as buscas.


Passo 5 — Busca por palavras-chave (BM25)

GET /artigos-tecnologia/_search
{
  "query": {
    "match": {
      "conteudo": "aplicação lenta"
    }
  }
}

Observe os resultados — quais artigos retornaram e com qual score.


Passo 6 — Busca semântica

GET /artigos-tecnologia/_search
{
  "query": {
    "semantic": {
      "field": "conteudo_semantico",
      "query": "aplicação lenta"
    }
  }
}

Compare com os resultados da busca por palavras-chave. A busca semântica deve retornar artigos sobre queries lentas de banco de dados e monitoramento de latência — mesmo sem a palavra "lenta" estar nesses documentos.


Passo 7 — Hybrid Search com RRF

GET /artigos-tecnologia/_search
{
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "match": {
                "conteudo": "aplicação lenta"
              }
            }
          }
        },
        {
          "standard": {
            "query": {
              "semantic": {
                "field": "conteudo_semantico",
                "query": "aplicação lenta"
              }
            }
          }
        }
      ],
      "rank_window_size": 10,
      "rank_constant": 60
    }
  }
}

Compare os três resultados: BM25, semântico e híbrido. Observe como o RRF combina os rankings das duas abordagens.


Passo 8 — Testando a inferência diretamente

Para entender o que o ELSER está fazendo por baixo, você pode chamar o endpoint de inferência diretamente:

POST /_inference/sparse_embedding/.elser-2-elastic
{
  "input": ["aplicação lenta"]
}

A resposta mostra os tokens expandidos e seus pesos — é a representação esparsa que o ELSER gerou para o texto de busca.


11.5 - Laboratório 2: Playground e RAG na Elastic Cloud

Neste laboratório vamos criar uma conta na Elastic Cloud, conectar um modelo de linguagem externo e usar o Playground para fazer perguntas em linguagem natural sobre os dados indexados.

Pré-requisito: API key de um provedor de LLM. As opções mais acessíveis são:

  • OpenAI: platform.openai.com — pago por uso, mas o custo para o lab é mínimo (centavos)
  • Google AI Studio (Gemini): aistudio.google.com — oferece tier gratuito com limite de requisições
  • Qualquer provedor compatível com a Open Inference API da Elastic

Passo 1 — Criar a conta na Elastic Cloud

  1. Acesse cloud.elastic.co
  2. Clique em Start free trial — não é necessário cartão de crédito
  3. Escolha o provedor de cloud (AWS, GCP ou Azure) e a região mais próxima
  4. Clique em Create deployment
  5. Aguarde o deployment ser criado — leva em torno de 2 a 3 minutos
  6. Na tela de confirmação, copie e salve a senha do usuário elastic — ela é exibida apenas uma vez

O trial gratuito dura 14 dias e inclui até 2GB de armazenamento. É suficiente para todos os labs deste capítulo.


Passo 2 — Acessar o Kibana do deployment Cloud

  1. No painel da Elastic Cloud, clique em Open Kibana
  2. Faça login com o usuário elastic e a senha salva no passo anterior
  3. Verifique que está no ambiente Cloud — a URL vai ter o formato https://xxxxx.kb.us-east-1.aws.elastic-cloud.com

Passo 3 — Indexar dados no deployment Cloud

Vamos criar um índice com dados de documentação técnica para usar como base de conhecimento no RAG.

No Dev Tools do Kibana Cloud:

POST /_bulk
{ "index": { "_index": "base-conhecimento", "_id": "1" } }
{ "titulo": "Como configurar autenticação JWT", "conteudo": "JWT (JSON Web Token) é um padrão para transmissão segura de informações entre partes. Para configurar JWT em uma API REST: 1) Gere um secret key seguro. 2) No login, crie um token assinado com o payload do usuário e o secret key. 3) Nas requisições subsequentes, o cliente envia o token no header Authorization: Bearer <token>. 4) O servidor valida a assinatura do token antes de processar a requisição." }
{ "index": { "_index": "base-conhecimento", "_id": "2" } }
{ "titulo": "Diagnóstico de lentidão no Elasticsearch", "conteudo": "Quando o Elasticsearch está lento, verifique: 1) Heap usage — se acima de 85%, o GC está pressionado. 2) Thread pool rejections — indica sobrecarga de indexação ou busca. 3) Shard count — muitos shards pequenos geram overhead. 4) Slow log — ative com index.search.slowlog.threshold.query.warn: 2s para capturar queries lentas. 5) Hot threads — use GET /_nodes/hot_threads para ver o que está consumindo CPU." }
{ "index": { "_index": "base-conhecimento", "_id": "3" } }
{ "titulo": "Boas práticas de ILM para logs", "conteudo": "Para logs com ILM: 1) Use rollover com max_primary_shard_size de 50GB — não por número de documentos, que varia muito. 2) Na fase warm, aplique forcemerge com max_num_segments: 1 e reduza réplicas para 1. 3) Na fase cold, reduza réplicas para 0. 4) Configure wait_for_snapshot na fase delete para garantir backup antes da remoção. 5) Monitore índices com _ilm/explain?only_errors=true periodicamente." }
{ "index": { "_index": "base-conhecimento", "_id": "4" } }
{ "titulo": "Estratégias de escalabilidade horizontal", "conteudo": "Para escalar horizontalmente um cluster Elasticsearch: 1) Adicione nodes do mesmo tipo que o gargalo — se a busca está lenta, adicione nodes data. 2) Verifique o ratio de shards por GB de heap — máximo 20 shards/GB. 3) Use data tiers para distribuir dados por temperatura. 4) Considere dedicated coordinating nodes em clusters com muitas buscas concorrentes. 5) Monitore o file descriptor usage — deve ficar abaixo de 80% do limite configurado." }
{ "index": { "_index": "base-conhecimento", "_id": "5" } }
{ "titulo": "Configuração de segurança do Elasticsearch", "conteudo": "Segurança no Elasticsearch 9.x vem ativada por padrão. Checklist de segurança para produção: 1) TLS no transport layer — configure com certificados próprios ou use os gerados pelo autoconfiguration. 2) TLS no HTTP layer — obrigatório para não expor credenciais em texto plano. 3) Troque a senha do usuário elastic imediatamente após a instalação. 4) Crie usuários com roles específicas — nunca use elastic em produção. 5) Configure o IP do network.host — não use 0.0.0.0 em produção sem firewall." }

Passo 4 — Configurar o conector de LLM

  1. No Kibana Cloud, acesse Menu → Search → Playground
  2. Clique em Connect to an LLM
  3. Selecione o provedor — OpenAI ou Google Gemini
  4. Cole sua API key no campo correspondente
  5. Clique em Save

O Playground vai confirmar que o LLM está conectado com uma mensagem verde "LLM Connected".


Passo 5 — Selecionar os dados e fazer perguntas

  1. No Playground, clique em Add data sources
  2. Selecione o índice base-conhecimento
  3. Clique em Save

Agora você pode fazer perguntas em linguagem natural. Tente:

  • "Como posso diagnosticar lentidão no meu cluster?"
  • "Qual a configuração recomendada de ILM para logs?"
  • "Quantos shards posso ter por GB de heap?"

Observe que as respostas são geradas com base nos documentos indexados — não no conhecimento geral do LLM. O Playground mostra as citações dos documentos usados para gerar cada resposta.


Passo 6 — Explorar a query Elasticsearch por baixo

  1. Clique em Query na barra superior do Playground
  2. Você verá a query Elasticsearch que está sendo executada para recuperar o contexto
  3. Experimente modificar a query — trocar semantic por match e observar como as respostas mudam

Passo 7 — Ver o código gerado

  1. Clique em View code no Playground
  2. O Kibana gera o código Python completo do pipeline RAG
  3. Esse código pode ser baixado e usado como ponto de partida para uma aplicação real

11.6 - Connectors — sincronizando fontes externas

Os Connectors da Elastic permitem sincronizar dados de fontes externas para o Elasticsearch automaticamente — sem precisar escrever código de integração. Os dados ficam disponíveis para busca, análise e uso como base de conhecimento no RAG.

Fontes suportadas

Connector Fonte
SharePoint Documentos e páginas do Microsoft 365
Confluence Documentos e espaços do Confluence
GitHub Repositórios, issues e pull requests
Jira Tickets e projetos
Google Drive Documentos do Google Workspace
S3 Arquivos em buckets da AWS
PostgreSQL / MySQL Tabelas de bancos de dados relacionais
ServiceNow Tickets e base de conhecimento
Slack Mensagens e canais
Elasticsearch Sincronização entre clusters

Como funciona

  1. Você configura o conector no Kibana com as credenciais da fonte
  2. O conector faz a sincronização inicial — traz todos os dados existentes
  3. Sincronizações incrementais mantêm o índice atualizado automaticamente
  4. Os dados ficam disponíveis para busca e para uso no Playground

Caminho: Menu → Search → Content → Connectors → Create connector


11.7 - Cross-cluster Search

O Cross-cluster Search (CCS) permite executar buscas em múltiplos clusters Elasticsearch a partir de um único ponto. É útil quando os dados estão distribuídos geograficamente — por regulamentação, latência ou organização — mas você precisa de uma visão unificada.

Configuração básica:

PUT /_cluster/settings
{
  "persistent": {
    "cluster.remote.cluster-remoto.seeds": ["ip-remoto:9300"]
  }
}

Busca cross-cluster:

GET /cluster-remoto:indice-remoto,indice-local/_search
{
  "query": {
    "match_all": {}
  }
}

A sintaxe cluster-remoto:indice-remoto especifica o cluster e o índice de destino. Você pode combinar índices locais e remotos na mesma query.

Em produção, o CCS exige que os clusters tenham configuração de segurança compatível e que as roles dos usuários incluam permissão de remote_cluster_client privilege.


11.8 - Laboratório 3: Reindexação e migração de dados

Neste laboratório vamos usar o _reindex para migrar dados do índice artigos-tecnologia criado no Lab 1 para um novo índice com mapping atualizado, aplicando uma pipeline de ingestão durante a migração.

Passo 1 — Verificar o índice original

GET /artigos-tecnologia/_count
GET /artigos-tecnologia/_mapping

Passo 2 — Criar o índice de destino com mapping atualizado

PUT /artigos-tecnologia-v2
{
  "mappings": {
    "properties": {
      "titulo": {
        "type": "text",
        "fields": { "keyword": { "type": "keyword" } }
      },
      "conteudo": { "type": "text" },
      "conteudo_semantico": {
        "type": "semantic_text",
        "inference_id": ".elser-2-elastic"
      },
      "data_migracao": { "type": "date" },
      "versao": { "type": "keyword" }
    }
  }
}

Passo 3 — Criar uma pipeline para enriquecer os documentos durante a migração

PUT /_ingest/pipeline/pipeline-migracao-v2
{
  "description": "Adiciona metadados de migração aos documentos",
  "processors": [
    {
      "set": {
        "field": "data_migracao",
        "value": "{{_ingest.timestamp}}"
      }
    },
    {
      "set": {
        "field": "versao",
        "value": "v2"
      }
    },
    {
      "set": {
        "field": "conteudo_semantico",
        "copy_from": "conteudo"
      }
    }
  ]
}

Passo 4 — Executar o reindex

POST /_reindex
{
  "source": {
    "index": "artigos-tecnologia"
  },
  "dest": {
    "index": "artigos-tecnologia-v2",
    "pipeline": "pipeline-migracao-v2"
  }
}

Passo 5 — Verificar o resultado

GET /artigos-tecnologia-v2/_count
GET /artigos-tecnologia-v2/_search
{
  "size": 1
}

Confirme que os documentos foram migrados com os novos campos data_migracao e versao, e que o campo conteudo_semantico foi populado e está gerando embeddings.

Passo 6 — Criar um alias para abstrair a versão

POST /_aliases
{
  "actions": [
    { "remove": { "index": "artigos-tecnologia", "alias": "artigos" } },
    { "add":    { "index": "artigos-tecnologia-v2", "alias": "artigos" } }
  ]
}

A partir desse momento, qualquer aplicação que busca no alias artigos automaticamente passa a usar o índice v2 — sem nenhuma mudança no código da aplicação.

Limpeza

DELETE /artigos-tecnologia
DELETE /artigos-tecnologia-v2
DELETE /_ingest/pipeline/pipeline-migracao-v2

11.9 - Operações adicionais do Elasticsearch

Snapshot e Restore

Abordado em detalhes na seção de Administração (wiki-secao-adm). O Snapshot é o mecanismo de backup nativo do Elasticsearch — copia os segmentos do Lucene para um repositório externo (filesystem, S3, GCS, Azure). O Restore recupera índices de um snapshot existente.

Comandos essenciais:

PUT /_snapshot/repositorio_lab
{
  "type": "fs",
  "settings": { "location": "/opt/elastic/snapshots", "compress": true }
}
 
PUT /_snapshot/repositorio_lab/snapshot_manual
 
POST /_snapshot/repositorio_lab/snapshot_manual/_restore
{
  "indices": ["artigos-tecnologia"]
}

Clone this wiki locally