Curso
Há pouco tempo, os computadores funcionavam como bibliotecários eficientes, porém literais. Se você buscasse por "batalhas de robôs gigantes", eles só encontrariam títulos com essas palavras exatas. Uma correspondência perfeita como "Kaiju Mech Warfare" passaria batido. Os computadores reconheciam palavras, mas perdiam a música—faltavam entendimento, nuances e contexto. Essa foi a era da busca por palavras-chave, que foi nossa melhor opção por muitos anos.
Então veio a revolução. Inspirada no cérebro humano, a inteligência artificial desenvolveu uma nova forma de aprender. Em vez de simplesmente memorizar palavras, a IA passou a compreender as relações entre elas. Entendeu que "rei" se relaciona com "homem" assim como "rainha" com "mulher". Reconheceu que "feliz", "alegre" e "eufórico" compartilham o mesmo território emocional, enquanto "soturno" está em um universo à parte.
Como a IA conseguiu isso? Criando um mapa de significados.
O que é busca vetorial? O mapa de significados
Imagine uma galáxia vasta e multidimensional onde cada conceito—uma palavra, uma frase, uma imagem, uma música—é uma estrela. Nessa galáxia, estrelas com significados semelhantes se agrupam, enquanto as não relacionadas ficam a anos-luz de distância.
Uma vector embedding é simplesmente a coordenada de uma estrela nessa galáxia. É uma lista de números (por exemplo, [0.12, -0.45, 0.89, ...]) que localiza com precisão um conceito nesse mapa de significados.
Vector search é a habilidade revolucionária de navegar por esse mapa. Quando você pede "um filme sobre um garoto órfão que descobre que é um bruxo", não buscamos essas palavras exatas. Em vez disso, nós:
- Encontramos a coordenada (o vetor) da sua pergunta no mapa.
- Localizamos as estrelas vizinhas mais próximas (nossos enredos de filmes).
As estrelas mais próximas representam os resultados semanticamente mais semelhantes. É assim que a IA evoluiu de uma bibliotecária literal para uma sábia que entende o que você realmente quer dizer.
Por que isso é tão importante?
Buscar por significado em vez de palavras-chave impulsiona aplicações modernas de IA em diversos setores. Essa capacidade permite:
- Netflix recomendar filmes desconhecidos que têm a mesma "vibe" do seu histórico de visualização.
- Spotify montar playlists com músicas que soam como as suas favoritas, independente do gênero ou época.
- Chatbots e LLMs entenderem a intenção por trás das suas perguntas e entregarem respostas relevantes e contextuais.
- Sites de e-commerce exibirem produtos visualmente semelhantes às imagens que você envia.
A busca vetorial aproxima a intenção humana dos dados digitais, transformando a forma como interagimos com a informação. Essa tecnologia faz os sistemas digitais parecerem menos mecânicos e mais como colaboradores intuitivos.
Vamos aprender: criando seu primeiro app de busca vetorial com MongoDB
Bem-vindo à nova fronteira da busca! O MongoDB lançou o Vector Search no Atlas. Isso permite armazenar e consultar embeddings vetoriais (de texto, imagens ou áudio) diretamente no MongoDB—sem precisar de um banco de dados vetorial separado como o Pinecone ou o Weaviate.
Neste tutorial, vamos construir um mecanismo simples, porém poderoso, de recomendação de tênis usando Python e MongoDB Atlas. Você vai aprender a transformar texto em representações numéricas com significado (vetores) e depois usar o Vector Search nativo do Atlas para encontrar produtos com descrições semelhantes.
O que você vai aprender
- Como se conectar com segurança a um cluster do MongoDB Atlas usando a biblioteca pymongo do Python.
- Como criar e inserir documentos contendo embeddings vetoriais.
- Como gerar embeddings vetoriais a partir de texto usando a biblioteca sentence-transformers.
- Como criar um índice de Vector Search na interface do MongoDB Atlas.
- Como executar uma consulta de busca semântica usando o pipeline de agregação $vectorSearch.
Pré-requisitos
- Uma conta gratuita no MongoDB Atlas
- Python 3.9+ instalado localmente
- Instale as dependências:
pip install pymongo sentence-transformers numpy
Passo 1: crie um cluster no MongoDB Atlas
- Acesse o Atlas.

- Crie um cluster gratuito. Crie um usuário e copie o nome de usuário e a senha.

- Após criar o usuário, clique em Choose a connection method. Você verá a primeira tela abaixo. Clique em Drivers e vá para a segunda tela. Selecione Python como driver e a versão apropriada. Copie a string de conexão.


- Vá em Database Deployments → Clique em Browse Collections → Crie um novo banco de dados:
- Nome do banco:
vectorDemo - Nome da coleção:
items

- Ative o Vector Search:
- Na interface do MongoDB Atlas, vá em Vector Search Indexes → Crie um novo índice para
items. - Nome do índice: “vector_index”
- Use esta definição:
{
"fields": [
{
"type": "vector",
"path": "embedding",
"numDimensions": 768,
"similarity": "cosine"
}
]
}
Observação: 768 é o tamanho do embedding que usaremos com o modelo sentence-transformers.


Entendendo a definição do índice:
"type": "vector": Informa ao MongoDB Atlas que este é um índice vetorial."path": "embedding": Crucialmente, aponta para o campo nos documentos que contém os vetores."numDimensions": 768: Isso precisa corresponder à dimensionalidade dos vetores produzidos pelo nosso modelo."similarity": "cosine": O algoritmo usado para medir a “proximidade” dos vetores. É excelente para similaridade baseada em texto.
Passo 2: conecte o Python ao MongoDB Atlas
Obtenha sua string de conexão do MongoDB Atlas:
- No MongoDB Atlas, clique em Connect → Drivers → Python.
- Substitua
<username>,<password>e<cluster-url>no trecho abaixo.
from pymongo import MongoClient
# Replace with your Atlas connection string
uri = "mongodb+srv://<username>:<password>@<cluster-url>/vectorDemo?retryWrites=true&w=majority"
client = MongoClient(uri)
db = client["vectorDemo"]
collection = db["items"]
print("Connected to MongoDB Atlas")
# Clear existing
collection.delete_many({})
print("Cleared collection.")
Passo 3: gere embeddings com Python
Vamos usar o SentenceTransformers para converter texto em embeddings.
from sentence_transformers import SentenceTransformer
# Choose model: higher-quality for search -> "sentence-transformers/all-mpnet-base-v2" (768-d)
# If you need faster/smaller: "all-MiniLM-L6-v2" (384-d)
MODEL_NAME = "sentence-transformers/all-mpnet-base-v2"
# MODEL_NAME = "all-MiniLM-L6-v2"
# Note: if you use all-mpnet-base-v2, your Atlas vector index must use numDimensions: 768
# If you use all-MiniLM-L6-v2, index numDimensions: 384
model = SentenceTransformer(MODEL_NAME)
def embed_text(text: str):
return model.encode(text).tolist()
Passo 4: insira documentos de exemplo com embeddings
Vamos armazenar algumas descrições de produtos no MongoDB com seus embeddings.
# Each product includes name, description, list of features, use_cases and tags.
products = [
# Marathon / long-distance running (explicit!)
{
"name": "MarathonPro 3000",
"description": "Designed specifically for marathon and ultra distance running: maximum cushioning, breathable knit upper, responsive midsole and engineered heel support for long-run comfort.",
"features": ["marathon", "long-distance", "max cushioning", "breathable", "support"],
"category": "shoes",
"use_cases": ["marathon", "long-distance running", "road running"],
"tags": ["running", "endurance", "comfort"]
},
{
"name": "Enduro LongRun",
"description": "Lightweight long-run trainer optimized for marathon pacing with added cushioning, stable platform, and enhanced forefoot energy return for hours of comfortable running.",
"features": ["long-run", "lightweight", "energy return", "cushioning"],
"category": "shoes",
"use_cases": ["marathon", "road running"],
"tags": ["running","marathon","comfort"]
},
# Road running / neutral
{
"name": "Red Road Runner",
"description": "Neutral road running shoe for daily training: breathable mesh, moderate cushioning and responsive ride; suitable for tempo runs and long easy runs.",
"features": ["road running", "breathable", "moderate cushioning"],
"category": "shoes",
"use_cases": ["training", "road running", "tempo runs"],
"tags": ["running","training"]
},
# Trail running (explicit trail)
{
"name": "TrailMaster RidgeGrip",
"description": "Trail-running shoe with aggressive outsole, rock plate for protection, waterproof upper, designed for technical trails and rugged terrain.",
"features": ["trail", "high grip", "rock plate", "waterproof"],
"category": "shoes",
"use_cases": ["trail running", "hiking", "off-road"],
"tags": ["trail","outdoors"]
},
# Tennis & court
{
"name": "CourtPro Tennis",
"description": "Court shoe with lateral support, non-marking sole and reinforced toe; built for tennis footwork and short intense bursts, not for long-distance running.",
"features": ["court", "lateral support", "non-marking sole"],
"category": "shoes",
"use_cases": ["tennis","court sports"],
"tags": ["tennis","sport"]
},
# Formal
{
"name": "Oxford Leather Formal",
"description": "Classic leather formal shoe for office and events: polished leather, sturdy sole, refined silhouette.",
"features": ["formal", "leather", "office"],
"category": "shoes",
"use_cases": ["formal wear","office"],
"tags": ["formal","leather"]
},
# Hiking
{
"name": "Alpine Trek Boots",
"description": "High-ankle hiking boots with waterproof membrane, ankle support and durable lugged outsole for mountain treks.",
"features": ["hiking", "waterproof", "ankle support", "lugged outsole"],
"category": "shoes",
"use_cases": ["hiking","trekking","outdoor"],
"tags": ["outdoors","hiking"]
},
# Casual sneakers
{
"name": "Classic Canvas Sneaker",
"description": "Casual everyday canvas sneaker with rubber sole, comfortable fit for daily wear and walking.",
"features": ["casual","canvas", "everyday"],
"category": "shoes",
"use_cases": ["casual","walking"],
"tags": ["casual"]
},
# Cross-trainer
{
"name": "CrossFit Trainer",
"description": "Stable cross-trainer shoe engineered for gym workouts, short sprints, and lateral movements; flexible yet supportive.",
"features": ["cross-train","stable","gym"],
"category": "shoes",
"use_cases": ["gym","cross-training"],
"tags": ["training","gym"]
},
# Cleats
{
"name": "Pro Soccer Cleats",
"description": "Low-profile football/soccer cleats with studded outsole; optimized for grip on grass and agility.",
"features": ["cleats","studs","agility"],
"category": "shoes",
"use_cases": ["soccer","football"],
"tags": ["sports","cleats"]
}
]
# ---------- Create 'canonical_text' to improve embedding quality for better scoring ----------
for p in products:
# join features and others into one rich text blob
features = ", ".join(p["features"])
uses = ", ".join(p["use_cases"])
tags = ", ".join(p["tags"])
canonical = f"{p['name']}. {p['description']}. Features: {features}. Use cases: {uses}. Tags: {tags}."
p["canonical_text"] = canonical
# ---------- Embed canonical_text----------
print("Embedding items...")
for p in products:
p["embedding"] = embed_text(p["canonical_text"])
# ---------- Insert into MongoDB ----------
collection.insert_many(products)
Ao usar o insert_many, fazemos uma única operação em lote eficiente no banco de dados.
Passo 5: faça sua primeira busca vetorial
Chegou a hora do passo final e mais empolgante! Vamos usar o framework de agregação do MongoDB e o $vectorSearch—um operador para encontrar os melhores tênis para a consulta.
query_text = "25k long running best shoes"
query_embedding = embed_text(query_text)
pipeline = [
{
"$vectorSearch": {
"index": "vector_index", # Use the vector search index you created
"path": "embedding",
"queryVector": query_embedding,
"numCandidates": 100,
"limit": 3
}
},
{
"$project": {
"name": 1,
"description":1,
"score": {"$meta": "vectorSearchScore"}
}
}
]
results = collection.aggregate(pipeline)
print(f"\nSearch results for: '{query_text}'\n")
for r in results:
print(f"- {r['name']} (score: {r['score']:.4f})")
Dissecando o pipeline $vectorSearch:
$vectorSearch: Este é o operador central. Ele compara de forma eficiente nosso queryVector com o campo indexadoplot_embeddingde todos os documentos.$project: Esta etapa remodela a saída. Incluímosnameedescription, excluímos oruídodo_ide outros campos e, principalmente, adicionamos um campo score usando$meta: "vectorSearchScore". Esse score, de 0 a 1, indica o quão semelhante o resultado é à nossa consulta.
Saída esperada
Se tudo estiver configurado corretamente, você verá algo assim:
Search results for: '25k long running best shoes'
- MarathonPro 3000 (score: 0.7980)
- Red Road Runner (score: 0.7479)
- Enduro LongRun (score: 0.7389)
Perceba que “MarathonPro 3000” aparece no topo—exatamente como esperado.
Parabéns! Você acabou de construir um aplicativo de busca vetorial do zero. Aprendeu a se conectar a um banco de dados, criar e validar dados, gerar embeddings vetoriais e aproveitar o poder do MongoDB Atlas para encontrar informação de um jeito realmente inteligente. Bem-vindo ao futuro da interação com dados.
Conclusão
Neste tutorial, você aprendeu a:
- Conectar ao MongoDB Atlas usando Python e pymongo, formando a base para aplicações orientadas a banco de dados.
- Criar embeddings (apenas texto) a partir de um catálogo de produtos realista com modelos de alta qualidade como all-mpnet-base-v2 e armazená-los no MongoDB com normalização adequada.
- Construir um dataset rico e estruturado usando canonical_text (nome, descrição, recursos, casos de uso, tags), o que melhora a relevância dos embeddings.
- Executar buscas por similaridade vetorial com a etapa de agregação $vectorSearch do MongoDB para encontrar produtos semanticamente semelhantes com base em consultas em linguagem natural.
Próximos passos (mão na massa)
- Armazene avaliações de usuários e crie um mecanismo de busca semântica.
Experimente diferentes métricas de similaridade (dotProduct, euclidean).
FAQs
Por que o canonical_text é mais rico do que apenas a descrição do produto?
canonical_text inclui recursos, casos de uso e tags para oferecer mais contexto aos embeddings—ajudando o modelo a capturar melhor a intenção do usuário na busca vetorial.
Por que eu escolhi all-mpnet-base-v2 em vez de MiniLM ou CLIP?
all-mpnet-base-v2 (768 dims) oferece representações semânticas mais fortes para similaridade somente de texto em comparação com modelos leves (384 dims). CLIP é excelente em tarefas multimodais, mas é menos preciso para consultas apenas de texto com nuances.
Essa abordagem escala para grandes volumes de dados?
Sim! O MongoDB Atlas suporta índices vetoriais com milhões de documentos. Em grande escala, ajustar parâmetros do índice (por exemplo, numCandidates) e usar re-ranking apenas no top-N mantém a performance alta.
E se eu quiser busca multimodal (texto + imagem) em seguida?
Você pode migrar para um modelo de embedding multimodal (como o CLIP ou alternativas open source), normalizar os embeddings, armazená-los do mesmo jeito e depois usar a mesma estratégia de busca vetorial + re-ranking para pesquisa em mídia mista.
Como saber qual dimensionalidade de modelo usar?
Dimensões maiores (por exemplo, 512, 768, 1024, 2056) tendem a capturar melhor a semântica, mas exigem mais armazenamento e computação. Use modelos menores (384) para velocidade ou experimentos e suba para 768 quando a precisão for crucial.
Posso combinar busca vetorial com busca de texto completo?
Com certeza. O MongoDB Atlas permite combinar uma etapa $search usando consultas compound—misturando filtros de texto completo BM25 com knnBeta ou $vectorSearch—para experiências híbridas ricas de busca.

Engenheiro de Software @ Uber

