Búsqueda semántica con $vectorSearch

Guarda embeddings junto a tus documentos y busca por significado con un índice vectorial.

Con $vectorSearch buscas documentos por lo que significan y no por las palabras exactas. Los vectores se guardan como un campo más del documento y el índice vive en los mismos nodos que los datos: no hace falta otra base de datos.

Esta guía usa Python, PyMongo y el modelo all-MiniLM-L6-v2 de sentence-transformers, que da vectores de 384 dimensiones. Cualquier modelo de embeddings sirve; ajusta numDimensions a su tamaño.

Shell
pip install pymongo sentence-transformers

1. Guarda los documentos con su vector

Python
from pymongo import MongoClient
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("all-MiniLM-L6-v2")  # 384 dimensions
client = MongoClient("mongodb://app:<password>@node-01:27017/?tls=true&tlsCAFile=./ca.pem")
articles = client.kb.articles

docs = [
    {"title": "Add a node", "body": "Create an enrollment token and start the binary with --join."},
    {"title": "Drain a node", "body": "teseladb admin node drain moves its replicas before you shut it down."},
]
for doc in docs:
    doc["embedding"] = model.encode(doc["title"] + ". " + doc["body"]).tolist()
articles.insert_many(docs)

2. Crea el índice vectorial

Python
from pymongo.operations import SearchIndexModel

articles.create_search_index(SearchIndexModel(
    name="vector",
    type="vectorSearch",
    definition={"fields": [
        {"type": "vector", "path": "embedding", "numDimensions": 384, "similarity": "cosine"}
    ]},
))

3. Busca por significado

Python
query = model.encode("how do I take a machine out of the cluster?").tolist()
results = articles.aggregate([
    {"$vectorSearch": {"index": "vector", "path": "embedding", "queryVector": query,
                       "numCandidates": 100, "limit": 3}},
    {"$project": {"title": 1, "score": {"$meta": "vectorSearchScore"}}},
])
for r in results:
    print(round(r["score"], 3), r["title"])

La pregunta no contiene la palabra «drain», pero el resultado más cercano es el artículo que la explica.

4. Filtra y afina

  • Añade un campo filter al índice ({"type": "filter", "path": "categoria"}) y pasa filter en $vectorSearch para buscar solo en una categoría.
  • Sube numCandidates para mejorar la exactitud a cambio de tiempo, o usa exact: true para comparar con todos los vectores. Con exact, el resultado es el mismo en cualquier réplica.
  • Un documento insertado aparece en la búsqueda en cuanto se confirma la escritura.

Última actualización