-
Notifications
You must be signed in to change notification settings - Fork 3
11 ‐ Search
O Elastic Stack é organizado em torno de quatro soluções: Observabilidade, Segurança, Busca e a infraestrutura que sustenta todas elas. Este capítulo cobre o pilar de Busca com foco nas funcionalidades de inteligência artificial nativas do Elasticsearch 9.x.
A evolução da busca no Elasticsearch seguiu uma trajetória clara, e cada camada resolveu um problema real sem substituir a anterior:
1. Busca por palavras-chave (BM25)
↓ resolve: busca relevante por termos
2. Busca semântica (ELSER)
↓ resolve: busca por significado, não por palavras exatas
3. Busca híbrida (BM25 + semântica com RRF)
↓ resolve: combina precisão de palavras-chave com entendimento semântico
4. RAG — Retrieval Augmented Generation
↓ resolve: respostas em linguagem natural fundamentadas nos seus dados
5. Agentes de IA com acesso a ferramentas
resolve: automação inteligente de fluxos de trabalho
Em 2026, uma implementação de busca moderna usa todas essas camadas. O Elasticsearch 9.x implementa todas elas nativamente — sem dependência de ferramentas externas.
O BM25 (Best Match 25) é o algoritmo de ranking padrão do Elasticsearch desde a versão 5.x. Seu nome vem da 25ª iteração de refinamentos do modelo probabilístico BM (Best Match) desenvolvido nas décadas de 1970 e 1980.
O BM25 calcula a relevância de um documento para uma query com base em dois fatores:
TF (Term Frequency) — com saturação: quanto mais vezes um termo aparece no documento, maior o score. Mas a relação não é linear — há um ponto de saturação. A décima ocorrência da palavra não vale dez vezes a primeira. Isso evita que documentos com spam de palavras-chave dominem os resultados.
IDF (Inverse Document Frequency): termos raros no índice valem mais do que termos comuns. Se a palavra "Elasticsearch" aparece em poucos documentos, ela é discriminante. Se a palavra "the" aparece em todos os documentos, ela não diz nada sobre relevância.
score(doc, query) = Σ IDF(t) × TF(t, doc) × (k1 + 1) / (TF(t, doc) + k1 × (1 - b + b × |doc| / avgdl))
Onde k1 controla a saturação da frequência do termo e b controla a normalização pelo tamanho do documento.
Quando o BM25 funciona muito bem:
- Busca por termos técnicos precisos: siglas, nomes de produtos, IDs, versões
- Usuários que sabem exatamente a terminologia do domínio
- Busca em campos de baixa cardinalidade com valores controlados
Limitação fundamental: o BM25 compara tokens. Ele não entende que "timeout de conexão" e "falha de rede" descrevem o mesmo problema. Se o documento usa palavras diferentes das que o usuário digitou, o BM25 não encontra.
Para entender o ELSER, é necessário entender o conceito de embedding — a representação de texto como números.
Modelos de linguagem como BERT, E5 e GPT foram treinados em bilhões de textos e aprenderam padrões de co-ocorrência de palavras. Com esse aprendizado, eles conseguem transformar qualquer texto em um vetor numérico — uma lista de números de alta dimensão — onde textos semanticamente parecidos ficam próximos no espaço vetorial.
Dense vectors (vetores densos): todos os valores são informativos. Um modelo como o E5 produz vetores de 768 dimensões onde cada número carrega significado contextual. A similaridade entre dois textos é calculada como a distância geométrica entre seus vetores.
"timeout de conexão" → [0.23, -0.41, 0.87, 0.12, -0.33, ...] (768 dimensões)
"falha de rede" → [0.21, -0.39, 0.85, 0.11, -0.31, ...] ← próximos
"receita de bolo" → [-0.92, 0.11, -0.34, 0.76, 0.55, ...] ← distantes
O Elasticsearch armazena esses vetores em campos do tipo dense_vector e usa o algoritmo HNSW (Hierarchical Navigable Small World) para busca aproximada eficiente — encontrar os vetores mais próximos sem precisar comparar com todos os documentos.
O ELSER (Elastic Learned Sparse EncodeR) é o modelo de busca semântica desenvolvido e treinado pela Elastic. Diferente dos modelos de dense vector, o ELSER usa sparse vectors — uma representação radicalmente diferente.
Em vez de produzir um vetor denso com centenas de dimensões numéricas, o ELSER expande o texto em um dicionário de termos com pesos de relevância. Cada texto se torna um conjunto de termos relacionados, onde os pesos indicam o grau de associação:
Texto original: "Como diagnosticar lentidão em uma aplicação web"
Representação ELSER:
{
"latência": 0.89,
"performance": 0.84,
"throughput": 0.78,
"tempo_resposta": 0.75,
"gargalo": 0.71,
"monitoramento": 0.68,
"profiling": 0.62,
"otimização": 0.58,
"cache": 0.51,
...
(centenas de outros termos com pesos menores)
}
Esses termos não são sinônimos. São associações aprendidas pelo modelo a partir do contexto em que as palavras co-ocorrem nos dados de treinamento. O modelo aprendeu que textos sobre "lentidão em aplicação web" estão relacionados a "latência", "throughput", "profiling" — mesmo que essas palavras não estejam no texto original.
Por que sparse em vez de dense?
Vetores densos têm sempre o mesmo número de dimensões ativas. Vetores sparse têm a maioria dos valores zerados — só os termos relevantes têm peso. Isso torna a busca mais eficiente: em vez de calcular distância geométrica em 768 dimensões, o Elasticsearch faz uma interseção de termos não-zero, similar ao que o índice invertido já faz para BM25. É mais rápido e mais explicável — você consegue ver quais termos foram usados para determinar a relevância.
Características importantes do ELSER:
- Treinado com dados em inglês — recomendado para documentos e queries em inglês
- Não requer fine-tuning — funciona out-of-the-box em qualquer domínio sem retreinamento
- Disponível via EIS (Elastic Inference Service) como endpoint gerenciado — sem necessidade de ML nodes locais
- Para outros idiomas, a Elastic recomenda o E5 multilingual (
inference_id: ".multilingual-e5-small-elastic")
Antes do tipo semantic_text existir (GA no Elasticsearch 9.x), configurar busca semântica exigia:
- Criar o índice com campo de tipo
sparse_vectorpara armazenar os embeddings - Configurar uma Ingest Pipeline com processor
inferencepara gerar os embeddings na indexação - Usar a query
sparse_vectorna busca, referenciando o endpoint de inferência manualmente
O semantic_text automatiza todo esse fluxo. Você declara o campo com o tipo e o inference_id do modelo, e o Elasticsearch:
- Gera os embeddings automaticamente quando um documento é indexado
- Executa a inferência correta quando você usa a query
semanticnesse campo - Trata do chunking (divisão de textos longos em partes menores para os modelos)
"meu_campo": {
"type": "semantic_text",
"inference_id": ".elser-2-elastic"
}Após conectar o EIS via Cloud Connect, o endpoint .elser-2-elastic está disponível automaticamente — sem precisar criar ou configurar nada.
Boas práticas de modelagem com
semantic_text: mantenha um campotextseparado com o mesmo conteúdo do camposemantic_text. O campotexté usado para busca BM25 (busca híbrida) e para recuperar o texto original nos resultados. O camposemantic_textarmazena os embeddings e é usado para busca semântica. Usecopy_topara manter os dois em sincronia automaticamente.
A busca híbrida combina os dois mundos: a precisão do BM25 para termos técnicos exatos e o entendimento semântico do ELSER para linguagem natural. O algoritmo de fusão é o RRF (Reciprocal Rank Fusion).
Como o RRF funciona:
Para cada documento, o RRF calcula uma pontuação com base em sua posição no ranking de cada abordagem:
RRF_score(doc) = Σ 1 / (rank_constant + rank_em_cada_lista)
Onde rank_constant (padrão: 60) evita que documentos no topo de uma única lista dominem o resultado. Um documento ranqueado em 1º em BM25 e em 2º em busca semântica vai acumular mais pontos do que um documento que aparece apenas em uma das listas. Isso produz um resultado que favorece documentos relevantes em ambas as abordagens.
Na prática com semantic_text: o RRF usa dois retrievers padrão (standard). O primeiro executa match no campo de texto. O segundo executa match no campo semantic_text — e o Elasticsearch detecta automaticamente que o campo é semantic_text e executa busca semântica, não BM25.
RAG é uma arquitetura que combina um sistema de busca com um modelo de linguagem. O problema que ela resolve: LLMs são treinados até uma certa data e não têm acesso a dados privados ou recentes. Se você perguntar ao GPT-4 sobre a configuração específica de um sistema interno da sua empresa, ele vai gerar uma resposta plausível mas incorreta — isso se chama alucinação.
O fluxo do RAG:
1. Usuário faz uma pergunta em linguagem natural
↓
2. Sistema busca no Elasticsearch os documentos mais relevantes
(usando busca semântica, BM25 ou híbrida)
↓
3. Os documentos recuperados + a pergunta são enviados ao LLM como contexto
↓
4. LLM gera uma resposta em linguagem natural
baseada EXCLUSIVAMENTE no contexto fornecido
↓
5. A resposta inclui citações dos documentos usados
Por que não mandar todos os documentos direto para o LLM?
Dois motivos práticos. Primeiro, limite de contexto: LLMs têm um limite de tokens que aceitam de entrada — tipicamente 8k a 128k tokens. Em uma base de conhecimento com milhares de documentos, é impossível enviar tudo. O Elasticsearch recupera apenas os mais relevantes — geralmente 3 a 10 documentos. Segundo, custo: APIs de LLM cobram por token processado. Mandar milhares de documentos em cada requisição seria economicamente inviável.
O RAG é o que o Search Playground e o AI Assistant implementam por baixo — busca no Elasticsearch, contexto para o LLM, resposta fundamentada.
O Cloud Connect é o mecanismo que conecta um cluster Elasticsearch self-managed aos serviços gerenciados da Elastic Cloud — sem mover dados, sem alterar a arquitetura existente.
O EIS (Elastic Inference Service) é o serviço de inferência que roda na infraestrutura de GPU da Elastic Cloud. Ao conectar o cluster via Cloud Connect:
- O processamento de inferência (geração de embeddings, execução de LLMs) acontece nos GPUs da Elastic
- Os textos que precisam de inferência são transmitidos para processamento e os resultados voltam para o cluster
- Os dados indexados permanecem no cluster local — nada é migrado
- O Elasticsearch cria automaticamente os endpoints de inferência no cluster local
Endpoints criados automaticamente após conectar o EIS:
| Endpoint | Tipo | Uso |
|---|---|---|
.elser-2-elastic |
Sparse embedding | Busca semântica em inglês (ELSER via GPU) |
.multilingual-e5-small-elastic |
Dense embedding | Busca semântica multilingual |
.rerank-elastic |
Reranking | Reordenação de resultados por relevância |
| LLMs gerenciados | Chat/completion | AI Assistant, Agent Builder, Playground |
Requisito: licença Enterprise no cluster self-managed. O trial de 30 dias é suficiente. A conta na Elastic Cloud pode ser o tier gratuito — apenas a API key é necessária.
- Acesse cloud.elastic.co
- Clique em Start free trial — sem necessidade de cartão de crédito
- Confirme o email e faça login no painel da Elastic Cloud
- Clique no avatar no canto superior direito → Organization
- Clique na aba API keys → Create API key
- Dê o nome
cloud-connect-treinamento→ clique em Create API key - Copie e salve a key gerada — ela é exibida apenas uma vez
Não é necessário criar nenhum deployment na Cloud. Apenas a conta gratuita é necessária para gerar a Cloud Connect API key.
- No Kibana local, abra a barra de busca global (
Ctrl+/ou clique na lupa) - Pesquise por Cloud Connect
- Clique em Cloud Connect nos resultados — você verá a tela de setup com os campos de conexão
- Cole a Cloud Connect API key gerada no Passo 1
- Clique em Connect
O Kibana vai verificar a chave e confirmar a conexão com uma mensagem de sucesso.
- Após conectar ao Cloud Connect, a tela de Cloud connected services exibe os serviços disponíveis
- Localize o Elastic Inference Service
- Clique em Connect
- Aguarde a configuração — alguns segundos
No Kibana Dev Tools, execute:
GET /_inferenceVocê verá os endpoints criados automaticamente pelo EIS:
{
"endpoints": [
{ "inference_id": ".elser-2-elastic", ... },
{ "inference_id": ".multilingual-e5-small-elastic", ... },
{ "inference_id": ".rerank-elastic", ... }
]
}Esses endpoints estão prontos para uso imediato. Nenhum ML node local foi utilizado.
- Acesse Stack Management → AI → GenAI Settings
- Confirme que o painel lateral agora mostra o modelo conectado — o aviso "No Large Language Model detected" desapareceu
- Na seção Documentation, clique em Install nos dois pacotes disponíveis:
- Elastic documentation — documentação oficial do produto
- Security labs — base de conhecimento de segurança da Elastic
- Aguarde a instalação de ambos
Esses pacotes alimentam o AI Assistant com informações atualizadas sobre o Elastic Stack, tornando as respostas mais precisas e fundamentadas na documentação real do produto.
O AI Assistant é o assistente de IA integrado ao Kibana, acessível pelo ícone no canto superior direito da interface. Ele tem duas capacidades que o diferenciam de um LLM genérico:
Acesso ao cluster em tempo real: o assistente pode executar queries, verificar o estado de índices e analisar dados do cluster durante a conversa, sem que você precise copiar e colar nada.
Base de conhecimento indexada: com a documentação oficial instalada, o assistente usa RAG para fundamentar as respostas na documentação atual do produto — não no conhecimento de treinamento do LLM que pode estar desatualizado.
Clique no ícone AI Agent no canto superior direito do Kibana.
Execute cada uma das perguntas abaixo e observe como o assistente interage com o cluster em tempo real:
Pergunta 1 — Estado do cluster:
Qual é o estado atual do meu cluster? Quantos nodes temos e quais são seus roles?
O assistente vai executar GET /_cat/nodes e GET /_cluster/health e interpretar os resultados em linguagem natural.
Pergunta 2 — Análise de índices:
Quais são os 5 maiores índices do cluster em termos de tamanho em disco?
Algum deles tem algum problema?
Pergunta 3 — Diagnóstico de ILM:
Verifique se há algum índice com erro no ILM. Se houver, explique o que
pode ter causado e como resolver.
Pergunta 4 — Criação de aggregation:
Preciso de uma aggregation que mostre, no índice saldo:
- A média de saldo por estado
- O total de saldo por estado
- O estado com o maior saldo médio
Gere a query completa e explique cada parte.
Copie a query gerada e execute no Dev Tools para verificar que funciona.
Pergunta 5 — Query de diagnóstico:
Crie uma query que encontre os 3 índices que mais cresceram em número
de documentos nos últimos 7 dias, usando a _cat API.
Com a documentação oficial instalada, o assistente cita as fontes:
Pergunta 6:
Qual é a diferença entre forcemerge e o processo de merge automático
do Elasticsearch? Quando devo usar cada um?
Pergunta 7:
Quando devo usar o tipo de campo nested em vez de object?
Me dê um exemplo prático de quando a diferença importa.
Pergunta 8:
Quais são as regras práticas de sizing de shards que a Elastic recomenda?
Pergunta 9:
Faça uma análise completa do meu cluster e me diga:
1. O estado geral de saúde
2. Se há algum shard não alocado e por quê
3. Se o uso de heap está adequado
4. Quais índices podem precisar de atenção
O assistente vai executar múltiplas queries ao cluster, coletar as informações e produzir um relatório em linguagem natural.
O Agent Builder permite criar assistentes de IA customizados com comportamento específico, instruções definidas e acesso controlado a fontes de dados. Enquanto o AI Assistant é um assistente genérico do Elastic Stack, o Agent Builder permite criar assistentes especializados para casos de uso do seu negócio.
Casos de uso reais:
- Agente de suporte técnico que responde sobre os seus sistemas internos com acesso à documentação interna indexada
- Agente de análise que interpreta alertas do SIEM e sugere próximos passos
- Agente de observabilidade que diagnostica problemas com acesso aos dados de APM e métricas
Menu → Search → Agent Builder
(ou pesquise "Agent Builder" na barra de busca global)
Clique em Create agent.
No campo Instructions, cole o seguinte conteúdo:
Você é ElasticBot, um especialista técnico em Elasticsearch e Elastic Stack
criado pela BKTECH.
Responda sempre em português brasileiro, de forma técnica e objetiva.
Você pode ajudar com:
- Explicar conceitos do Elasticsearch (mapping, shards, ILM, aggregations,
analyzers, busca semântica)
- Criar e explicar queries, aggregations e configurações
- Diagnosticar problemas de performance e sugerir soluções
- Explicar erros e como resolvê-los
- Recomendar boas práticas de implementação
Diretrizes de comportamento:
- Sempre forneça exemplos de queries ou configurações quando fizer sentido
- Quando não tiver certeza de algo, diga claramente que não sabe
- Nunca invente APIs ou parâmetros que não existem
- Se a pergunta estiver fora do seu escopo técnico, diga isso claramente
- Cite as fontes dos documentos quando usar a base de conhecimento
Formato das respostas:
- Use markdown para formatar queries e blocos de código
- Seja objetivo — evite introduções longas
- Quando der um exemplo, explique o que cada parte faz
- Em Knowledge sources, clique em Add index
- Selecione o índice
base-conhecimento-elasticsearchque será criado no Lab 4 - O agente vai usar os documentos desse índice como base de conhecimento — RAG aplicado ao agente
Nota: crie o índice do Lab 4 antes de concluir este passo, ou volte a adicionar o índice após a criação.
No painel de teste à direita da tela:
O que é ELSER e como ele se diferencia de modelos de dense vector?
Meu cluster está com status yellow. Quais são as causas mais comuns
e como diagnostico?
Como configuro uma ILM policy para logs que devem ficar hot por 7 dias,
warm por 30 dias e serem deletados após 90 dias?
Observe como o agente combina o conhecimento do LLM com os documentos da knowledge source — quando o assunto está indexado, ele vai citar o conteúdo.
- Dê o nome ElasticBot ao agente
- Clique em Save
- Clique no ícone AI Agent no canto superior direito
- Clique na seta ao lado do nome "AI Agent" para ver a lista de assistentes
- Selecione ElasticBot
O ElasticBot agora está disponível para toda a equipe que acessa esse Kibana.
O Search Playground é a interface de RAG do Kibana para desenvolvedores. Com o EIS conectado, os LLMs gerenciados pela Elastic estão disponíveis automaticamente — sem configurar API key de provedor externo.
Diferença em relação ao Agent Builder: o Playground expõe toda a mecânica do RAG — a query Elasticsearch por baixo, o contexto enviado ao LLM, o código Python gerado. É uma ferramenta de experimentação e desenvolvimento, não de uso final pela equipe.
Menu → Search → Playground
Com o EIS conectado, o Playground mostra "LLM Connected".
Antes de usar o Playground, vamos criar um índice com documentação técnica para usar como knowledge base.
PUT /base-conhecimento-elasticsearch
{
"mappings": {
"properties": {
"titulo": { "type": "text", "copy_to": "titulo_semantico" },
"conteudo": { "type": "text", "copy_to": "conteudo_semantico" },
"categoria":{ "type": "keyword" },
"titulo_semantico": {
"type": "semantic_text",
"inference_id": ".elser-2-elastic"
},
"conteudo_semantico": {
"type": "semantic_text",
"inference_id": ".elser-2-elastic"
}
}
}
}Indexe os documentos:
POST /_bulk
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "1" } }
{ "titulo": "Diagnóstico de lentidão no Elasticsearch", "categoria": "performance", "conteudo": "Quando o Elasticsearch está lento, o diagnóstico começa pelo heap usage. Se o uso de heap estiver acima de 85%, o garbage collector está trabalhando demais e causando pausas de latência imprevisível. Verifique com GET /_nodes/stats?metric=jvm. O segundo passo é verificar thread pool rejections com GET /_cat/thread_pool?v — rejeições indicam sobrecarga de indexação ou busca. O terceiro passo é analisar o slow log: ative com PUT /meu-indice/_settings com index.search.slowlog.threshold.query.warn em 2s para capturar queries lentas. Por último, use GET /_nodes/hot_threads para ver qual código está consumindo CPU no momento." }
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "2" } }
{ "titulo": "Boas práticas de sizing de shards", "categoria": "arquitetura", "conteudo": "O tamanho ideal de um shard é entre 10GB e 50GB. Shards maiores que 50GB ficam lentos para recovery após falha e para operações de merge. Shards menores que 1GB geram overhead desnecessário de metadados e coordenação de busca. A regra dos 20 shards por GB de heap é fundamental para planejamento: um cluster com 3 nodes de 4GB de heap cada tem 12GB de heap total e comporta no máximo 240 shards. Em ambientes com rollover diário e retenção de 90 dias, isso equivale a 90 índices com até 2 shards cada. O número de shards primários não pode ser alterado após a criação do índice — planeje com antecedência." }
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "3" } }
{ "titulo": "Configuração de ILM para ambientes de produção", "categoria": "operações", "conteudo": "Em produção, a ILM policy para logs deve ter rollover baseado em tamanho de shard primário (max_primary_shard_size: 50gb) e não em número de documentos, pois o volume varia muito. Na fase warm, aplique forcemerge com max_num_segments: 1 para compactar todos os segmentos em um, readonly para bloquear escritas, e reduza réplicas para 1 com allocate. Na fase cold, reduza réplicas para 0 — use snapshots como proteção em vez de réplicas. Sempre configure wait_for_snapshot na fase delete em ambientes com requisitos de compliance, para garantir que o backup existe antes da remoção. Monitore erros com GET /*/_ilm/explain?only_errors=true periodicamente." }
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "4" } }
{ "titulo": "Mapping: text vs keyword e quando usar cada um", "categoria": "mapping", "conteudo": "O tipo text é para campos onde você quer fazer busca de texto livre — o Elasticsearch analisa o conteúdo, tokeniza e indexa cada palavra separadamente. Use em campos de descrição, mensagens, conteúdo de logs. O tipo keyword é para valores que você vai filtrar exatamente, ordenar ou agregar — o valor é indexado como está, sem análise. Use em campos de status, UF, email, ID, categoria. A regra prática: se você vai fazer match query, use text. Se vai fazer term query, sort ou terms aggregation, use keyword. Quando precisar dos dois no mesmo campo, use multi-field com fields: { keyword: { type: keyword } }. O erro mais comum é definir CEP como text — o analyzer divide 01310-100 em dois tokens 01310 e 100, e filtros por CEP exato nunca encontram nada." }
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "5" } }
{ "titulo": "Segurança no Elasticsearch: checklist de produção", "categoria": "segurança", "conteudo": "No Elasticsearch 9.x, segurança vem ativada por padrão. O checklist de produção inclui: 1) Nunca usar o usuário elastic em aplicações — crie usuários específicos com as permissões mínimas necessárias. 2) Configurar TLS no transport layer entre nodes — use certificados próprios em produção, não os auto-assinados do autoconfiguration. 3) Configurar TLS no HTTP layer — sem TLS, senhas são transmitidas em texto plano. 4) Usar o Keystore para armazenar senhas em configurações do Logstash e Beats — nunca em texto plano nos arquivos de configuração. 5) Restringir network.host — não use 0.0.0.0 em produção sem firewall configurado. 6) Habilitar audit logging para rastrear acessos e operações em dados sensíveis." }
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "6" } }
{ "titulo": "Reindexação: quando e como usar o _reindex", "categoria": "operações", "conteudo": "A operação _reindex é necessária sempre que você precisa mudar o mapping de um índice com dados existentes — adicionar um campo semantic_text, mudar o tipo de um campo, adicionar um analyzer. O processo padrão é criar o novo índice com o mapping correto, executar o _reindex do antigo para o novo com uma pipeline de enriquecimento se necessário, e por último trocar o alias para apontar para o novo índice. O alias garante transparência para as aplicações — elas continuam usando o mesmo nome sem saber que o índice por baixo mudou. Em índices grandes, execute com wait_for_completion: false e monitore o progresso com GET /_tasks?actions=*reindex&detailed=true. O _reindex não é atômico — durante a migração, novas escritas vão para o índice antigo. Considere usar um alias de escrita e migrar em fases para zero downtime." }
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "7" } }
{ "titulo": "Aggregations: como escolher entre metric, bucket e pipeline", "categoria": "queries", "conteudo": "Metric aggregations calculam um valor sobre um conjunto de documentos: avg, sum, min, max, value_count, cardinality, percentiles, stats. Use quando quer um número como resultado. Bucket aggregations dividem documentos em grupos: terms agrupa por valor único, date_histogram por intervalo de tempo, range por faixas numéricas. Use quando quer distribuição ou agrupamento. Pipeline aggregations operam sobre resultados de outras aggregations: avg_bucket calcula a média entre buckets, max_bucket encontra o bucket com maior valor, derivative calcula taxa de variação. As três se combinam: agrupe por data com date_histogram, calcule a média de resposta dentro de cada bucket com avg, e use derivative para ver se a latência está aumentando ou diminuindo ao longo do tempo." }
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "8" } }
{ "titulo": "Elastic Agent vs Beats: quando usar cada um", "categoria": "ingestão", "conteudo": "O Elastic Agent substitui todos os Beats individuais com uma única instalação gerenciada centralmente pelo Fleet no Kibana. Em novas implementações, sempre use o Elastic Agent. Os Beats individuais ainda existem e são suportados, mas o desenvolvimento de novas funcionalidades está concentrado no Elastic Agent. A vantagem do Elastic Agent é gestão centralizada: você configura integrações, políticas e atualizações no Kibana e elas se propagam automaticamente para todos os agentes instalados. O Logstash continua sendo a melhor opção quando você precisa de transformações complexas na ingestão — parsing de formatos não padronizados, enriquecimento com fontes externas, roteamento condicional para múltiplos destinos. O Ingest Pipeline é a opção mais simples para enriquecimento básico que acontece dentro do próprio cluster, sem necessidade de ferramenta externa." }
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "9" } }
{ "titulo": "Busca semântica com ELSER: como funciona e quando usar", "categoria": "search-ai", "conteudo": "O ELSER (Elastic Learned Sparse EncodeR) é o modelo de busca semântica da Elastic. Diferente de modelos de dense vector, o ELSER expande o texto em termos associados com pesos de relevância. Quando você busca por 'aplicação lenta', o ELSER entende que isso está relacionado a latência, throughput, performance, gargalo, otimização — e encontra documentos que usam essa terminologia mesmo sem as palavras 'aplicação' ou 'lenta'. O ELSER é recomendado para documentos em inglês. Para português e outros idiomas, use o modelo E5 multilingual com inference_id .multilingual-e5-small-elastic. Configure usando o campo semantic_text — o Elasticsearch cuida automaticamente de gerar os embeddings na indexação e executar a busca semântica na query. Use busca híbrida com RRF para combinar ELSER com BM25, aproveitando os pontos fortes de cada abordagem." }
{ "index": { "_index": "base-conhecimento-elasticsearch", "_id": "10" } }
{ "titulo": "Cross-cluster Search: buscando em múltiplos clusters", "categoria": "arquitetura", "conteudo": "O Cross-cluster Search (CCS) permite executar uma única query em múltiplos clusters Elasticsearch simultaneamente. É útil quando os dados estão distribuídos geograficamente por regulamentação (dados de clientes europeus em cluster na Europa, dados brasileiros em cluster no Brasil) ou por organização (cluster de produção e cluster de histórico separados). Configure o cluster remoto com PUT /_cluster/settings incluindo cluster.remote.nome-do-cluster.seeds com o endereço e porta 9300 do cluster remoto. Execute buscas com a sintaxe nome-do-cluster:nome-do-indice no lugar do índice. Os resultados são consolidados pelo node coordenador local e retornados como se fossem de um único cluster. Requisito: os clusters devem ter configuração de TLS e os usuários devem ter a permissão remote_cluster_client." }- No Playground, clique em Add data sources
- Selecione o índice
base-conhecimento-elasticsearch - Clique em Save
Faça as perguntas abaixo e observe as respostas com citações:
Como diagnostico lentidão no meu cluster Elasticsearch?
Qual é a melhor configuração de ILM para logs em produção?
Quando devo usar text e quando devo usar keyword no mapping?
- Clique em Query na barra superior do Playground
- Observe a query que está sendo executada contra o índice
- O Playground usa busca semântica no campo
conteudo_semanticopara recuperar os documentos mais relevantes - Tente modificar a query para busca híbrida — substitua por:
{
"retriever": {
"rrf": {
"retrievers": [
{
"standard": {
"query": {
"match": {
"conteudo": "{{query}}"
}
}
}
},
{
"standard": {
"query": {
"semantic": {
"field": "conteudo_semantico",
"query": "{{query}}"
}
}
}
}
]
}
}
}- Observe como a qualidade das respostas muda com diferentes estratégias de recuperação
- Clique em View code
- O Kibana gera o pipeline RAG completo em Python
- Esse código é o ponto de partida para integrar o RAG em uma aplicação real
Neste laboratório exploramos as buscas diretamente via API para entender o que acontece por baixo do Playground e do AI Assistant.
PUT /artigos-tecnologia
{
"mappings": {
"properties": {
"titulo": {
"type": "text",
"copy_to": "titulo_semantico"
},
"conteudo": {
"type": "text",
"copy_to": "conteudo_semantico"
},
"categoria": { "type": "keyword" },
"titulo_semantico": {
"type": "semantic_text",
"inference_id": ".elser-2-elastic"
},
"conteudo_semantico": {
"type": "semantic_text",
"inference_id": ".elser-2-elastic"
}
}
}
}Explicação do mapping:
-
tituloeconteudosão campostextpara busca BM25 -
titulo_semanticoeconteudo_semanticosão campossemantic_textpara busca semântica -
copy_tocopia automaticamente o valor do campotextpara o camposemantic_text— você indexa apenas no campo original e os dois ficam sincronizados
POST /_bulk
{ "index": { "_index": "artigos-tecnologia", "_id": "1" } }
{ "titulo": "Falhas de rede em ambientes corporativos", "categoria": "infraestrutura", "conteudo": "Problemas de conectividade podem ocorrer em múltiplas camadas. Na camada física, falhas de cabo, switch ou placa de rede. Na camada de rede, roteamento incorreto, tabelas ARP desatualizadas ou MTU incompatível. Na camada de transporte, timeout de conexão TCP, janelas de congestionamento mal configuradas. Na camada de aplicação, DNS com TTL muito longo causando resolução desatualizada ou firewall bloqueando portas específicas. O diagnóstico começa pela camada mais baixa e sobe progressivamente." }
{ "index": { "_index": "artigos-tecnologia", "_id": "2" } }
{ "titulo": "Queries SQL lentas em bancos de dados", "categoria": "banco-de-dados", "conteudo": "Performance degradada em banco de dados tem causas variadas. A mais comum é ausência de índice nas colunas usadas em cláusulas WHERE e JOIN. O EXPLAIN ANALYZE revela o plano de execução e identifica table scans desnecessários. JOINs em tabelas muito grandes sem filtros seletivos multiplicam o custo. Subqueries correlacionadas executam uma vez para cada linha da query externa — reescrever como JOIN geralmente melhora. Estatísticas desatualizadas fazem o query planner escolher planos ineficientes — ANALYZE atualiza as estatísticas. Bloqueios de transação concorrente também causam lentidão que parece ser de query mas é de espera por lock." }
{ "index": { "_index": "artigos-tecnologia", "_id": "3" } }
{ "titulo": "Escalabilidade automática com Kubernetes HPA", "categoria": "cloud", "conteudo": "O Horizontal Pod Autoscaler escala automaticamente o número de pods com base em métricas. A configuração mais simples usa utilização de CPU: quando a média de CPU dos pods ultrapassa o threshold, novos pods são criados. Métricas customizadas permitem escalar com base em métricas de aplicação como requisições por segundo ou tamanho da fila. O Cluster Autoscaler complementa o HPA escalando os nodes quando não há recursos para alocar os pods. Configurar minReplicas e maxReplicas corretamente é crítico — minReplicas muito baixo pode deixar o serviço indisponível durante o scale up, maxReplicas muito alto pode gerar custo desnecessário." }
{ "index": { "_index": "artigos-tecnologia", "_id": "4" } }
{ "titulo": "Segurança em APIs: autenticação e autorização", "categoria": "segurança", "conteudo": "APIs devem implementar autenticação e autorização separadamente. Autenticação verifica a identidade — quem é você. Autorização verifica as permissões — o que você pode fazer. JWT (JSON Web Token) é o padrão mais usado para autenticação stateless: o servidor gera um token assinado com as claims do usuário, o cliente envia o token em cada requisição, o servidor valida a assinatura sem consultar banco de dados. OAuth 2.0 é o framework de autorização para delegar acesso a recursos de terceiros. Ataques comuns incluem injection de comandos, broken object level authorization (acessar dados de outros usuários trocando o ID), e rate limiting insuficiente que permite brute force." }
{ "index": { "_index": "artigos-tecnologia", "_id": "5" } }
{ "titulo": "Monitoramento de aplicações: métricas e alertas", "categoria": "observabilidade", "conteudo": "Monitoramento eficaz usa os três pilares: logs para o que aconteceu, métricas para o estado atual, traces para o caminho percorrido por cada requisição. Métricas de sistema (CPU, memória, disco, rede) indicam pressão de recursos. Métricas de aplicação (latência p50/p95/p99, taxa de erros, throughput) indicam a experiência do usuário. Alertas devem usar thresholds dinâmicos baseados em comportamento histórico, não valores fixos — um spike de CPU às 14h pode ser normal se sempre ocorre nesse horário. O erro comum é criar muitos alertas de baixa severidade que geram ruído e levam à fadiga de alertas, ignorando alertas importantes." }
{ "index": { "_index": "artigos-tecnologia", "_id": "6" } }
{ "titulo": "Cache: estratégias para reduzir latência", "categoria": "performance", "conteudo": "Cache reduz latência eliminando computação ou acesso ao banco de dados repetido. Cache em memória (Redis, Memcached) é o mais rápido mas volátil — adequado para dados que podem ser recalculados. Cache de banco de dados evita queries repetidas — válido para dados que mudam pouco. Cache HTTP com ETags e Cache-Control reduz tráfego de rede para recursos estáticos. A invalidação de cache é o problema mais difícil: invalidar cedo demais gera cache misses e pressão no backend, invalidar tarde demais serve dados desatualizados. Estratégias de invalidação incluem TTL fixo, invalidação por evento e cache-aside pattern. Em sistemas distribuídos, cache inconsistente entre nodes pode causar comportamento imprevisível." }
{ "index": { "_index": "artigos-tecnologia", "_id": "7" } }
{ "titulo": "Containers e Docker: boas práticas de produção", "categoria": "cloud", "conteudo": "Containers em produção exigem atenção a aspectos que não existem em desenvolvimento. Imagens devem ser mínimas — use imagens base slim ou distroless para reduzir superfície de ataque. Nunca rode como root dentro do container — configure USER no Dockerfile. Secrets não devem estar na imagem — use variáveis de ambiente injetadas em runtime ou serviços como HashiCorp Vault. Limite CPU e memória com resource requests e limits — sem limites, um container pode consumir todos os recursos do node. Implemente health checks para que o orquestrador saiba quando reiniciar containers com problema. Use multi-stage builds para separar a imagem de build da imagem de runtime, reduzindo significativamente o tamanho final." }
{ "index": { "_index": "artigos-tecnologia", "_id": "8" } }
{ "titulo": "Debugging de aplicações Python em produção", "categoria": "desenvolvimento", "conteudo": "Debugar aplicações Python em produção requer ferramentas não invasivas. Logging estruturado em JSON facilita a análise — use campos consistentes como timestamp, level, service, trace_id. O módulo logging padrão do Python suporta handlers diferentes por nível de severity. Profiling com cProfile ou py-spy revela hotspots de CPU sem parar a aplicação. Memory leaks são identificados com tracemalloc ou objgraph — procure por objetos que crescem indefinidamente. Para Django, o Django Debug Toolbar funciona em desenvolvimento, mas em produção use ferramentas APM como o Elastic APM que captura automaticamente queries SQL lentas, chamadas HTTP externas e exceções." }
{ "index": { "_index": "artigos-tecnologia", "_id": "9" } }
{ "titulo": "Message queues: RabbitMQ e Kafka comparados", "categoria": "arquitetura", "conteudo": "RabbitMQ e Kafka servem a propósitos diferentes apesar de ambos serem sistemas de mensageria. RabbitMQ é um message broker tradicional — foca em roteamento flexível de mensagens, delivery garantido e múltiplos patterns de exchange (direct, topic, fanout, headers). Adequado para workflows de tarefas, RPC assíncrono e integração de sistemas. Kafka é uma plataforma de streaming de eventos — foca em throughput alto, retenção de eventos por tempo configurável e replay de eventos. Adequado para event sourcing, pipelines de dados e processamento de streams. A diferença fundamental: no RabbitMQ, mensagens são consumidas e removidas. No Kafka, eventos são retidos e múltiplos consumidores podem ler o mesmo evento de forma independente." }
{ "index": { "_index": "artigos-tecnologia", "_id": "10" } }
{ "titulo": "Git: fluxos de trabalho para times distribuídos", "categoria": "desenvolvimento", "conteudo": "Times distribuídos precisam de convenções claras de fluxo de trabalho no Git. Gitflow usa branches de feature, develop e release — adequado para software com releases planejadas. Trunk-based development usa uma única branch principal com feature flags — adequado para times que praticam integração contínua. Conventional Commits padroniza mensagens de commit com tipos (feat, fix, chore, docs) facilitando geração automática de changelogs. Pull requests devem ter escopo pequeno — PRs grandes demoram para ser revisados e geram conflitos de merge. Branch protection rules evitam push direto na branch principal e exigem revisão de código e CI passando antes do merge." }Aguarde 30 a 60 segundos após o bulk insert. O EIS processa os campos
semantic_textem background. Execute o passo seguinte para verificar quando os embeddings estiverem prontos.
Verificar se os embeddings foram gerados:
GET /artigos-tecnologia/_search
{
"size": 1,
"_source": ["titulo", "categoria"]
}Se retornar documentos sem erro, os embeddings estão sendo processados. Para verificar um documento específico com os embeddings:
GET /artigos-tecnologia/_doc/1Execute a busca e anote os resultados — quais artigos retornaram e com qual score:
GET /artigos-tecnologia/_search
{
"query": {
"match": {
"conteudo": "sistema lento demora para responder"
}
},
"_source": ["titulo", "categoria"]
}Provavelmente retornará artigos que contêm palavras como "lento" ou "latência". O artigo sobre falhas de rede provavelmente não vai aparecer — mesmo que problemas de rede causem lentidão no sistema.
GET /artigos-tecnologia/_search
{
"query": {
"semantic": {
"field": "conteudo_semantico",
"query": "sistema lento demora para responder"
}
},
"_source": ["titulo", "categoria"]
}Compare com o resultado anterior. A busca semântica deve retornar artigos sobre cache, queries SQL lentas e monitoramento de latência — o ELSER entendeu que "sistema lento que demora para responder" está relacionado a performance, latência, throughput e otimização.
A busca híbrida usa o retriever com rrf. Para campos semantic_text, o segundo retriever usa match no campo semântico — o Elasticsearch detecta automaticamente o tipo e executa busca semântica:
GET /artigos-tecnologia/_search
{
"retriever": {
"rrf": {
"retrievers": [
{
"standard": {
"query": {
"match": {
"conteudo": "sistema lento demora para responder"
}
}
}
},
{
"standard": {
"query": {
"match": {
"conteudo_semantico": "sistema lento demora para responder"
}
}
}
}
],
"rank_window_size": 10,
"rank_constant": 60
}
},
"_source": ["titulo", "categoria"]
}Compare os três resultados. O RRF produz um resultado diferente de ambas as abordagens individuais — documentos bem posicionados em ambas as listas sobem, documentos que aparecem em apenas uma das listas ficam mais abaixo.
O mapping tem dois campos semânticos — você pode fazer busca em qualquer um:
GET /artigos-tecnologia/_search
{
"query": {
"bool": {
"should": [
{
"semantic": {
"field": "conteudo_semantico",
"query": "proteger sistema contra invasões",
"boost": 1.0
}
},
{
"semantic": {
"field": "titulo_semantico",
"query": "proteger sistema contra invasões",
"boost": 2.0
}
}
]
}
},
"_source": ["titulo", "categoria"]
}O campo de título recebe boost maior — um documento com título semanticamente relevante é priorizado sobre um documento que só menciona o assunto no conteúdo.
Busca semântica dentro de uma categoria específica:
GET /artigos-tecnologia/_search
{
"query": {
"bool": {
"must": [
{
"semantic": {
"field": "conteudo_semantico",
"query": "como melhorar a velocidade"
}
}
],
"filter": [
{
"term": {
"categoria": "performance"
}
}
]
}
},
"_source": ["titulo", "categoria"]
}O filtro por categoria é executado no filter context (sem cálculo de score, com cache), e a busca semântica é executada no must context (com score). Resultado: apenas artigos da categoria "performance" que sejam semanticamente relevantes para "como melhorar a velocidade".
O _reindex é a operação usada sempre que você precisa mudar o mapping de um índice existente — adicionar um campo semantic_text, mudar o tipo de um campo, aplicar um analyzer diferente.
POST /_reindex
{
"source": {
"index": "artigos-tecnologia"
},
"dest": {
"index": "artigos-tecnologia-v2"
}
}Acompanhar o progresso:
GET /_tasks?actions=*reindex&detailed=truePadrão de produção com alias:
POST /_aliases
{
"actions": [
{ "remove": { "index": "artigos-tecnologia", "alias": "artigos" } },
{ "add": { "index": "artigos-tecnologia-v2", "alias": "artigos" } }
]
}Qualquer aplicação que busca pelo alias artigos passa automaticamente a usar o novo índice — sem nenhuma mudança no código da aplicação.
Permite buscas em múltiplos clusters simultaneamente a partir de um único ponto.
Configurar o cluster remoto:
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 referencia o cluster e o índice. O node coordenador local consolida os resultados dos dois clusters e retorna como se fossem de um único índice.