Se você trabalha com Análise de Dados, Business Intelligence ou Melhoria de Processos, sabe que a regra de ouro de qualquer arquitetura é: lixo que entra, é lixo que sai (Garbage In, Garbage Out).
Nos artigos anteriores, vimos como o OpenSearch é incrível para buscas rápidas e criação de dashboards em tempo real. Nós simplesmente jogamos um dicionário Python (JSON) lá dentro e ele aceitou. Isso se chama Dynamic Mapping (Mapeamento Dinâmico).
É ótimo para testes rápidos no seu terminal (usando Zsh ou Fish, por exemplo), mas em produção, deixar o banco adivinhar o tipo do seu dado é um pesadelo de Governança de Dados. O campo que deveria ser um número inteiro (integer) de repente vira um texto (text) só porque um erro na sua aplicação enviou "100" em vez de 100. E adeus métricas precisas no seu dashboard!
Hoje, vamos aprender a criar um contrato de dados rigoroso usando Mappings no OpenSearch antes de injetar qualquer coisa com Python.
O que é o Mapping no OpenSearch?
Se você vem do mundo do SQL (como PostgreSQL) ou de Data Warehouses (como BigQuery), você está acostumado a rodar um CREATE TABLE definindo colunas e tipos (VARCHAR, INT, TIMESTAMP).
No OpenSearch, o equivalente ao Schema da tabela é o Mapping. É ele que diz ao motor de busca:
- Quais campos existem no documento.
- Qual é o tipo de dado de cada campo (ex: texto livre, palavra-chave exata, número, data).
- Como esses campos devem ser indexados para a busca.
A Diferença Crucial: Text vs Keyword 🔍
Antes de irmos para o código, você precisa entender a diferença entre os dois principais tipos de string no OpenSearch, pois isso afeta diretamente o Business Intelligence:
- Text: Usado para texto longo (descrições, e-mails, logs extensos). O OpenSearch "quebra" esse texto em palavras separadas. Se o campo tiver "Analista de Dados", você consegue buscar apenas por "Dados". Não serve para agregações ou gráficos de pizza.
-
Keyword: Usado para valores exatos (IDs, status, categorias, e-mails exatos). Ele salva a string inteira como um bloco só. É obrigatório usar
keywordse você quiser fazer filtros estritos ou montar gráficos e dashboards.
Passo 1: Definindo o Contrato (Governança na Prática) 📜
Vamos imaginar que estamos criando um índice para monitorar a Melhoria de Processos da empresa. Queremos garantir que os dados entrem perfeitamente tipados.
Vamos usar o uv e o Python para criar esse índice com um Mapping explícito.
from opensearchpy import OpenSearch
# Conectando ao cluster (assumindo que já está rodando via contêiner/OrbStack)
cliente = OpenSearch(
hosts=[{'host': 'localhost', 'port': 9200}],
use_ssl=False,
verify_certs=False
)
nome_indice = 'processos_governados_v1'
# Aqui está a nossa Governança de Dados: O Mapping!
mapeamento = {
"mappings": {
"properties": {
# Keyword: Perfeito para IDs e filtros exatos
"processo_id": {
"type": "keyword"
},
# Text + Keyword: Queremos buscar parte do nome, mas também agrupar em gráficos!
"analista_responsavel": {
"type": "text",
"fields": {
"exato": {
"type": "keyword"
}
}
},
# Integer: Para calcularmos médias de tempo depois no BI
"tempo_execucao_ms": {
"type": "integer"
},
# Date: O formato ISO8601 é o padrão ouro
"data_execucao": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
# Boolean: Apenas true ou false
"sucesso": {
"type": "boolean"
}
}
}
}
# Criando o índice COM o mapeamento definido
if not cliente.indices.exists(index=nome_indice):
cliente.indices.create(index=nome_indice, body=mapeamento)
print(f"✅ Índice '{nome_indice}' criado com regras estritas de Governança!")
else:
print(f"⚠️ O índice '{nome_indice}' já existe.")
Passo 2: Testando a Injeção de Dados 🧪
Agora que temos um contrato, o OpenSearch vai nos ajudar a manter a qualidade dos dados. Vamos tentar inserir dois documentos: um correto e um "sujo".
from datetime import datetime
# 1. Dado Correto (Vai passar liso)
dado_limpo = {
"processo_id": "PROC-2026-001",
"analista_responsavel": "Francisco",
"tempo_execucao_ms": 1450,
"data_execucao": datetime.utcnow().isoformat(),
"sucesso": True
}
cliente.index(index=nome_indice, body=dado_limpo, refresh=True)
print("✅ Dado limpo indexado com sucesso!")
# 2. Dado Sujo (Vai forçar um erro de Governança)
dado_sujo = {
"processo_id": "PROC-2026-002",
"analista_responsavel": "Larissa",
"tempo_execucao_ms": "quatrocentos", # ERRO INTENCIONAL: Enviando texto no lugar de número
"data_execucao": datetime.utcnow().isoformat(),
"sucesso": True
}
try:
cliente.index(index=nome_indice, body=dado_sujo)
except Exception as e:
print("\n❌ ERRO DE GOVERNANÇA DETECTADO PELO OPENSEARCH:")
print("O motor rejeitou o documento porque o tipo do dado estava errado.")
# Isso impede que o seu dashboard quebre no futuro!
Passo 3: O Poder do Campo "Multi-field" no BI 📊
Note que no nosso mapeamento, o campo analista_responsavel foi definido como text, mas ganhou um subcampo chamado exato do tipo keyword. Essa é a técnica mais poderosa para quem trabalha com dados!
Na hora de fazer buscas livres no Python (para encontrar qualquer log do Francisco, por exemplo), você busca assim:
analista_responsavel: "Francisco"
Mas, na hora de ir para o OpenSearch Dashboards criar um gráfico de barras com a volumetria de processos por analista, você vai apontar o eixo X do seu gráfico para:
analista_responsavel.exato
Isso garante que o nome não seja fatiado e as agregações do seu Business Intelligence sejam 100% precisas.
Conclusão
Governança de dados não é apenas sobre ter regras chatas, é sobre confiabilidade. Ao definir o mapeamento (Mapping) no OpenSearch antes de começar a injetar dados com seus scripts em Python, você garante que as métricas que chegam à diretoria ou aos times operacionais sejam sempre precisas, tipadas corretamente e prontas para análise em tempo real.
O mapeamento dinâmico é legal para protótipos, mas Mapeamento Explícito é a marca de um profissional de dados sênior.
Você costuma definir esquemas estritos nos seus bancos de dados NoSQL ou prefere deixar tudo dinâmico? Conta aí nos comentários!
Top comments (0)