Dan Levy

Búsqueda vectorial semántica y otros temas para ganarse a amigos y amantes

El panorama completo de la búsqueda: exacta, difusa, semántica, híbrida… y cuándo combinarlas todas.

La búsqueda no es una sola cosa, y la búsqueda semántica no sustituye al resto.

Panorama de la búsqueda vectorial: compara 16 opciones

Compara el despliegue, las licencias, las capacidades de búsqueda y el ajuste a cada carga de trabajo. A continuación se explican las columnas y se incluyen ejemplos de SQL.

Cómo leer esta comparación

Base de datosDespliegueLicenciaBúsqueda híbridaVectores dispersosInterfaz de consultaEmbeddings multimodales integradosÍndice en discoLímites de dimensión de los vectoresMejor opción para
pgvectorAutohospedado / gestionado (Supabase, Neon, RDS)OSS (PostgreSQL)Manual (RRF mediante SQL)❌✅ SQL completo❌✅ HNSW en disco16.000 almacenadas; 2.000 indexadas en vectorYa usas Postgres; cantidades moderadas de vectores
QdrantAutohospedado / CloudApache 2.0✅ BM25 nativo✅ Soporte maduro❌ (REST/gRPC)❌✅65.535Consultas filtradas a escala; metadatos complejos
WeaviateAutohospedado / CloudBSD 3✅ BM25 nativo + RRF✅❌ (GraphQL / gRPC)✅ mediante módulos✅65.535Patrones de acceso GraphQL; vectorización integrada
PineconeSolo CloudPropietaria✅ (añadida en 2024)✅❌❌✅ (sin servidor)20.000Simplicidad gestionada; sin equipo de operaciones
Milvus / ZillizAutohospedado / Cloud (Zilliz)Apache 2.0✅ Nativa✅✅ Similar a SQL (Milvus Query Language)✅✅ DiskANN32.768Escala de miles de millones; on-prem empresarial
ChromaIntegrado / autohospedadoApache 2.0❌❌❌❌❌65.535Solo desarrollo local y prototipos
LanceDBIntegrado / CloudApache 2.0✅❌✅ SQL mediante DataFusion✅ Nativa✅ (formato Lance)IlimitadaEdge / sin servidor; lakehouse multimodal
OramaIntegrado / CloudApache 2.0✅ Texto completo + vectorial❌❌❌❌VaríaAplicaciones JS/edge; búsqueda ligera para sitios y aplicaciones
TurbopufferSolo Cloud (sin servidor)Propietaria✅ BM25 + vectorial❌❌❌✅ (almacenamiento de objetos)16.000SaaS multiinquilino; millones de espacios de nombres
ElasticsearchAutohospedado / Elastic CloudSSPL / AGPLv3✅ RRF + sparse ELSER✅ (ELSER)✅ Query DSL❌✅ DiskBBQ4.096Ya usas la pila Elastic; búsqueda empresarial híbrida
OpenSearchAutohospedado / gestionado por AWSApache 2.0✅ RRF + Neural Search✅✅ Query DSL❌✅ FAISS + HNSW16.000Nativo de AWS; alternativa de código abierto a Elastic
VespaAutohospedado / CloudApache 2.0✅ Nativa✅ Tensores / ranking léxico✅ YQL✅ Tensores✅Efectivamente ilimitadaSistemas de búsqueda + ranking + recomendación
ClickHouseAutohospedado / CloudApache 2.0Manual❌✅ SQL completo❌✅ Columnar + HNSWVaríaAnalítica y registros con búsqueda vectorial junto al OLAP
MongoDB AtlasCloud / autohospedadoSSPL✅ Integrada❌✅ MQL + agregación❌✅ HNSW8.192Ya usas MongoDB; documentos y vectores en un mismo sistema
Redis (VSS)Autohospedado / Redis CloudRSALv2 / SSPL✅ (RediSearch)✅❌❌❌ Solo en RAM32.768Latencia ultrabaja; búsqueda vectorial en la capa de caché
MarqoCloud / autohospedadoApache 2.0✅❌❌✅ Enfoque nativo✅VaríaMultimodal de extremo a extremo: imagen + texto + vídeo

“Encuentra al usuario con el correo dan@example.com” y “búscame artículos sobre depuración para un ingeniero que acaba de empezar” se describen como búsquedas, pero como problemas de ingeniería tienen muy poco en común. La primera tiene una respuesta correcta y una búsqueda indexada O(log n). La segunda no tiene una respuesta correcta —solo relevancia— y exige comprender el lenguaje, la intención y el significado.

Los ingenieros más convincentes al tomar decisiones sobre búsqueda —los que ganan las discusiones y entregan el sistema adecuado— entienden todo el panorama. Saben a qué herramienta recurrir y por qué, y pueden explicarlo con claridad.

Este artículo cubre la capa semántica: qué hace realmente la búsqueda vectorial, cuándo gana y cuándo debería apartarse. La versión útil no es “generarlo todo como embeddings”. Es saber cuándo los vectores deben convivir con la búsqueda léxica, difusa y de coincidencia exacta dentro de una arquitectura híbrida.

La mitad léxica y difusa del panorama —tsvector, pg_trgm, pg_search— se encuentra en Guía de búsqueda de texto en Postgres 2026.


Términos utilizados en esta guía

Embedding — Una lista densa de números de coma flotante producida por un modelo, que representa una pieza de texto (o una imagen, audio, etc.) como un punto en un espacio de alta dimensión. El contenido relacionado semánticamente queda cerca; el contenido no relacionado queda muy lejos.

Búsqueda léxica — Búsqueda basada en la coincidencia exacta de palabras y tokens. Es rápida, determinista y adecuada para términos conocidos. No entiende sinónimos, paráfrasis ni equivalentes entre idiomas.

Búsqueda semántica — Búsqueda basada en el significado, no en los tokens. Una consulta como “¿cómo gestiono los tiempos de espera?” puede encontrar un documento titulado “configuración de políticas de reintento” sin palabras en común, porque sus embeddings están geométricamente cerca.

Vector — Una lista de números. En el contexto de la búsqueda, es la salida de un modelo de embeddings. La “búsqueda vectorial” encuentra los vectores más cercanos a un vector de consulta según la distancia geométrica.

FTS (búsqueda de texto completo) — La búsqueda léxica integrada de Postgres, basada en tsvector / tsquery. Divide el texto en tokens, aplica stemming y lo indexa para consultas por palabras clave. Es sólida para prosa y búsquedas de términos exactos; no entiende el significado.

BM25 — Un algoritmo de ranking para búsquedas léxicas (utilizado por Elasticsearch, Qdrant y otros). Puntúa los resultados según la frecuencia del término, ponderada por lo poco frecuente que sea en el corpus. Es mejor que la coincidencia directa de palabras clave; sigue siendo léxico.

HNSW (Hierarchical Navigable Small World) — El índice estándar de vecino más cercano aproximado para la búsqueda vectorial. Construye un grafo de proximidad en capas para realizar consultas de similitud rápidas y con alta exhaustividad. pgvector, Qdrant, Weaviate y la mayoría de los demás utilizan este índice.

RRF (Reciprocal Rank Fusion) — Un algoritmo para combinar listas de resultados ordenadas procedentes de varios sistemas de recuperación. Usa únicamente la posición en el ranking; no requiere normalizar las puntuaciones. Un resultado que aparece en posiciones altas tanto en las listas de FTS como en las vectoriales obtiene una puntuación combinada mayor que otro que solo domina en una de ellas.


Cómo encuentran contenido relacionado los embeddings

Los embeddings vectoriales convierten texto (o imágenes, audio, etc.) en una lista de números: un punto en un espacio de alta dimensionalidad. Un modelo de embeddings se entrena para que los textos relacionados semánticamente queden cerca en ese espacio. «Perro» y «canino» terminan cerca. «Correr un maratón» y «ejecutar un script de Python» quedan muy separados, aunque compartan una palabra.

La búsqueda por similitud en ese espacio encuentra los documentos cuyo significado está más cerca del significado de la consulta, independientemente de que compartan exactamente las mismas palabras.

Esto significa que:

La búsqueda léxica (tsvector, pg_trgm) no puede hacer nada de esto. Opera sobre palabras y caracteres, no sobre significados. Las herramientas no son intercambiables: resuelven problemas distintos.


Cuándo gana pgvector

Para construir RAG. La generación aumentada mediante recuperación (Retrieval-Augmented Generation) recupera los fragmentos de documentos cuyo significado está más cerca de la pregunta del usuario y luego se los pasa a un modelo de lenguaje como contexto. Ese paso de recuperación es una operación vectorial. FTS no encontrará paráfrasis, sinónimos ni coincidencias conceptuales que un fragmento relevante podría expresar de otra forma. La ventaja de pgvector frente a un almacén vectorial independiente es que se ejecuta dentro de la instancia de Postgres que ya tienes: no hay que desplegar, operar ni sincronizar datos con otro servicio.

Cuando los usuarios describen lo que quieren, no qué deben buscar. «Artículos sobre cómo ganar confianza como nuevo responsable» no contiene palabras clave que aparezcan de forma fiable en las publicaciones relevantes. «Un framework ligero para gestionar efectos secundarios» puede no utilizar esas palabras exactas en la documentación. La búsqueda vectorial coincide con la intención, no con la ortografía.

Para encontrar elementos similares. Productos relacionados, tickets de soporte parecidos, informes de errores duplicados, artículos que también podrían interesarte. «Encuentra incidencias similares a esta» es una búsqueda de vecinos más cercanos: generas el embedding del elemento y buscas sus vecinos geométricos. Hay una salvedad importante: la búsqueda vectorial siempre devuelve resultados, incluso cuando nada es realmente similar. En casos de deduplicación y recomendación, filtra usando un umbral mínimo de similitud (por ejemplo, similitud coseno ≥ 0,80) para evitar mostrar coincidencias de baja confianza como si fueran relevantes.

Deduplicación semántica. Antes de indexar contenido para RAG o búsqueda, a menudo necesitas identificar casi duplicados en el corpus: artículos revisados varias veces, tickets de soporte registrados por duplicado, entradas de la base de conocimiento con un solapamiento considerable. Genera los embeddings de los documentos y aplica un filtro por umbral de similitud coseno para marcar o fusionar los casi duplicados antes de que contaminen el índice. Así evitas que la recuperación devuelva varios fragmentos casi idénticos y diluya la ventana de contexto.

Búsqueda multilingüe. Los modelos de embeddings multilingües asignan el contenido semánticamente equivalente en distintos idiomas a vectores cercanos. Una consulta en español como «perder peso» puede coincidir con un artículo en inglés sobre «hábitos sostenibles para perder peso»: no comparten tokens, pero sí el mismo significado subyacente. FTS requiere configurar un diccionario para cada idioma y gestiona mal las consultas entre idiomas. pg_trgm no depende del idioma, pero sí de la ortografía; no es semántico.

Configuración de pgvector

Desde la instalación de la extensión hasta la consulta de similitud, la configuración se reduce a unas cuantas sentencias SQL:

CREATE EXTENSION IF NOT EXISTS vector;
ALTER TABLE documents ADD COLUMN embedding vector(1536);
-- HNSW is usually the first index to try for moderate-size datasets
CREATE INDEX documents_embedding_idx
ON documents USING hnsw (embedding vector_cosine_ops);
-- Semantic search query
SELECT id, title, 1 - (embedding <=> $1::vector) AS similarity
FROM documents
ORDER BY embedding <=> $1::vector
LIMIT 10;

<=> es la distancia coseno. 1 - cosine_distance produce la similitud coseno (1,0 = idéntico; 0,0 = ortogonal). Para ivfflat (la alternativa más antigua y rápida de construir), usa lists = sqrt(row_count) como punto de partida.

Cuándo la búsqueda vectorial devuelve una respuesta incorrecta


Combina palabras clave y vectores para consultas mixtas

La documentación técnica es el ejemplo más claro de un caso en el que ninguna de las dos herramientas basta por sí sola.

Los usuarios que buscan «cómo configurar los tiempos de espera» necesitan coincidencia conceptual: un artículo titulado «Configuración de políticas de reintento y límites de conexión» no comparte palabras clave, pero es exactamente lo que necesitan.

Esos mismos usuarios también buscan withRetry(), ECONNRESET y ERR_SOCKET_TIMEOUT. Estas cadenas exactas deben aparecer; la coincidencia semántica puede no encontrarlas de forma fiable, y un falso positivo —conceptualmente similar, pero no la API correcta— induce directamente a error.

La búsqueda vectorial resuelve las consultas conceptuales. FTS resuelve los términos exactos. Ninguna de las dos maneja bien ambos casos por sí sola.

La solución es la búsqueda híbrida: ejecuta ambas y fusiona los resultados.

Combina resultados ordenados con RRF

La fusión recíproca de rangos (Reciprocal Rank Fusion, RRF) es el algoritmo estándar para combinar listas ordenadas procedentes de distintos sistemas de recuperación. No necesita normalizar las puntuaciones entre sistemas: solo usa las posiciones en el ranking. Un resultado que aparece arriba en ambas listas obtiene una puntuación combinada mayor que uno que solo domina en una.

WITH fts_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, query) DESC) AS rank
FROM documents, to_tsquery('english', $1) query
WHERE search_vector @@ query
LIMIT 50
),
vector_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank
FROM documents
ORDER BY embedding <=> $2::vector
LIMIT 50
),
rrf AS (
SELECT
COALESCE(f.id, v.id) AS id,
COALESCE(1.0 / (60 + f.rank), 0) +
COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score
FROM fts_results f
FULL OUTER JOIN vector_results v ON f.id = v.id
)
SELECT d.id, d.title, rrf.rrf_score
FROM rrf
JOIN documents d ON d.id = rrf.id
ORDER BY rrf_score DESC
LIMIT 10;

El 60 del denominador es la constante de RRF. Los valores más altos amortiguan las diferencias de posición en el ranking; los más bajos las amplifican. El valor predeterminado, 60, funciona bien con la mayoría de los tipos de contenido.

RRF evita el problema más difícil de normalizar ts_rank —una puntuación de frecuencia logarítmica— frente a la distancia coseno —una medida geométrica—. No son comparables. RRF solo pregunta: «¿qué tan arriba apareció este resultado en cada lista?».

Añade trigramas para errores tipográficos y nombres

En una búsqueda orientada al usuario sobre contenido heterogéneo —donde en una misma sesión se puede buscar el nombre de una persona, un concepto o un término exacto—, la fusión de tres vías resuelve los tres casos:

WITH trgm_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY similarity(title, $1) DESC) AS rank
FROM documents
WHERE title % $1
LIMIT 50
),
fts_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY ts_rank(search_vector, to_tsquery('english', $1)) DESC) AS rank
FROM documents
WHERE search_vector @@ to_tsquery('english', $1)
LIMIT 50
),
vector_results AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY embedding <=> $2::vector) AS rank
FROM documents
ORDER BY embedding <=> $2::vector
LIMIT 50
),
rrf AS (
SELECT
COALESCE(t.id, f.id, v.id) AS id,
COALESCE(1.0 / (60 + t.rank), 0) +
COALESCE(1.0 / (60 + f.rank), 0) +
COALESCE(1.0 / (60 + v.rank), 0) AS rrf_score
FROM trgm_results t
FULL OUTER JOIN fts_results f ON t.id = f.id
FULL OUTER JOIN vector_results v ON COALESCE(t.id, f.id) = v.id
)
SELECT d.id, d.title, rrf.rrf_score
FROM rrf
JOIN documents d ON d.id = rrf.id
ORDER BY rrf_score DESC
LIMIT 10;

Esto resuelve coincidencias aproximadas de nombres (trigramas), coincidencias exactas de palabras clave (FTS) y consultas conceptuales (vector). Un único cuadro de búsqueda puede atender las tres intenciones del usuario.


Adapta cada superficie de búsqueda a sus tipos de consulta

Las aplicaciones reales rara vez tienen una única superficie de búsqueda. Suelen tener varias, cada una con una necesidad distinta:

SuperficieQué consultan los usuariosCapas recomendadas
Búsqueda en blogs y documentaciónPalabras clave + conceptosFTS + pgvector (RRF)
Búsqueda de nombres de usuarios/clientesNombres con errores tipográficospg_trgm
Búsqueda de productosNombres, descripciones, «similar a»pg_trgm + FTS + pgvector
Deduplicación de tickets de soporte«Problemas similares a este»Solo pgvector
Búsqueda interna de SKU/pedidosIdentificadores exactosÍndice B-tree
RAG sobre una base de conocimiento grandePreguntas en lenguaje naturalpgvector (documentos divididos en fragmentos)
«También te puede gustar» en comercio electrónicoSimilitud conductual + semánticapgvector
AutocompletadoPrefijo, tolerante a errores ortográficospg_trgm

No son casos hipotéticos. La mayoría de las aplicaciones con mucho contenido necesitan al menos dos superficies de búsqueda distintas, con formas de consulta diferentes. La tentación es elegir un enfoque y usarlo en todas partes —normalmente la búsqueda vectorial ahora, porque está de moda—. Eso lleva a generar embeddings costosos para problemas en los que un índice de trigramas habría sido más rápido, barato y correcto.

Añade una capa de búsqueda cuando falle un tipo de consulta

Añade una capa cuando aparezca un modo de fallo que la capa actual no pueda solucionar:


Cuándo ir más allá de pgvector

pgvector cubre buena parte de las necesidades de búsqueda de una aplicación antes de que necesites otra base de datos. El umbral aproximado depende de la cantidad de vectores, la configuración de los índices, la tasa de escritura, los filtros, el hardware y la concurrencia; por eso, considera cualquier regla del tipo «menos de 10 millones de vectores» como una hipótesis inicial que debes validar con benchmarks, no como un límite del producto. Cuando realmente se te queda pequeño —concurrencia muy alta, requisitos de latencia p99 muy baja, miles de millones de vectores o necesidades serias de aislamiento multiinquilino—, el panorama de las bases de datos vectoriales especializadas es amplio y merece la pena entenderlo.

Cómo leer la comparación

La búsqueda híbrida significa que la búsqueda por palabras clave con BM25 y la similitud vectorial se ejecutan en una sola consulta y se combinan mediante RRF. Sin ella, tienes que elegir un modo de búsqueda o fusionar dos consultas por tu cuenta.

Los vectores dispersos van más allá de BM25. Un vector disperso SPLADE tiene unas 30.000 dimensiones (una por término del vocabulario), con aproximadamente un 98 % de ceros. Las posiciones distintas de cero indican qué términos importan y en qué medida. Una consulta por «perros» también pondera «canino» y «mascota»: precisión de nivel BM25 más expansión de términos dentro de un índice vectorial. Si esta columna es falsa, necesitas una capa FTS separada para las consultas de términos exactos.

# SPLADE: ~30,000 dims, ~60 non-zero — only relevant vocabulary positions fire
def encode_splade(text: str) -> dict:
tokens = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
with torch.no_grad():
output = model(**tokens)
vec = torch.log1p(torch.relu(output.logits)).max(dim=1).values.squeeze()
return {"indices": vec.nonzero().squeeze().tolist(), "values": vec[vec != 0].tolist()}

SQL / similar a SQL trata, en realidad, de los filtros. Una búsqueda vectorial sin filtrado es una demo. Sigues necesitando el ámbito del inquilino, rangos de fechas, permisos y filtros por categoría. El SQL completo (pgvector, LanceDB) expresa todo eso junto a tus JOIN existentes. Las bases de datos especializadas usan objetos de filtro JSON (Qdrant, Pinecone), un DSL de consultas (Elasticsearch, Milvus) o GraphQL (Weaviate). Funcionan; SQL resulta más atractivo a medida que la lógica de filtrado se complica.

-- pgvector: vector similarity is just another expression
SELECT id, title, 1 - (embedding <=> $1) AS score
FROM documents
WHERE tenant_id = $2
AND category = ANY($3::text[])
AND created_at > NOW() - INTERVAL '90 days'
ORDER BY embedding <=> $1
LIMIT 10;
# Qdrant: equivalent filter as a Python object — same result, more ceremony
results = client.query_points(
collection_name="documents", query=query_embedding,
query_filter=models.Filter(must=[
models.FieldCondition(key="tenant_id", match=models.MatchValue(value=tenant_id)),
models.FieldCondition(key="category", match=models.MatchAny(any=categories)),
models.FieldCondition(key="created_at", range=models.DatetimeRange(gte=cutoff)),
]),
limit=10,
)

Multimodal nativo significa que la base de datos incluye modelos de embeddings para contenido que no es texto. Le pasas la URL de una imagen sin procesar y se encarga de vectorizarla. La mayoría de las bases de datos no dependen de un modelo de embeddings concreto: la canalización de embeddings corre por tu cuenta. Marqo y Weaviate (mediante los módulos CLIP/ImageBind) cierran ese circuito.

# Marqo: POST raw images, query with text — no external embedding step
mq.index("products").add_documents(
[{"id": "shoe-001", "image": "https://cdn.example.com/shoes/001.jpg"}],
tensor_fields=["image"]
)
results = mq.index("products").search(q="lightweight shoes for summer")
# Returns shoe-001 despite zero keyword overlap — CLIP handles the cross-modal match

El índice basado en disco es una palanca de costes. Los índices HNSW residentes en RAM pueden requerir varios GB de RAM por cada millón de vectores de 1536 dimensiones cuando se cuentan los vectores sin procesar, la sobrecarga del grafo y los metadatos. Las alternativas nativas de disco (Milvus DiskANN, Elasticsearch DiskBBQ, el formato Lance de LanceDB y la capa de almacenamiento de objetos de Turbopuffer) suelen intercambiar algo de latencia de consulta por un coste de infraestructura menor. En cargas RAG donde la latencia del modelo ya domina, ese intercambio suele merecer la pena y conviene validarlo con benchmarks.

El máximo de dimensiones es una migración agazapada en tu arquitectura. text-embedding-3-large usa 3072 dimensiones, Jina v3 puede generar embeddings más grandes y los modelos de investigación siguen empujando ese límite hacia arriba. Algunos servicios gestionados publican límites estrictos de dimensiones; otros documentan límites altos o ningún límite práctico para los modelos de embeddings habituales. Comprueba la documentación actual antes de comprometerte. Elige algo con margen; migrar un índice vectorial porque has alcanzado el límite de dimensiones es un sprint doloroso.

Compromisos operativos que la tabla no puede mostrar

La multitenencia de Turbopuffer está diseñada para manejar cantidades muy elevadas de espacios de nombres. Su posicionamiento público y las historias de sus clientes destacan cargas como el corpus grande y con muchos espacios de nombres de Notion. Si cada usuario u organización necesita una búsqueda vectorial aislada, esa arquitectura puede cambiar la economía del sistema, pero aun así debes medir con la forma que tengan tus propios inquilinos.

El modo embebido de LanceDB es lo más parecido a «SQLite para búsqueda vectorial». Se ejecuta dentro del proceso, no necesita servidor y funciona en Lambda, Cloudflare Workers y entornos edge. El formato columnar Lance hace que la ejecución embebida sea práctica a escala real.

Chroma destaca sobre todo en desarrollo/pruebas y despliegues de aplicaciones pequeñas. Si apuntas a corpus muy grandes, alta disponibilidad, operación con mucho uso de disco o búsqueda híbrida de primer nivel, evalúa un almacén orientado a producción antes de convertir el prototipo en infraestructura.

Vespa es lo que eliges cuando la recuperación es solo la mitad del producto. Combina recuperación léxica, búsqueda de vecinos más cercanos, tensores, expresiones de ranking, agrupación y serving en línea. Esa potencia es real, pero también lo son la complejidad operativa y la de modelado. Encaja mejor en equipos de búsqueda/recomendación que en «añadir búsqueda semántica a mi aplicación CRUD».

ClickHouse entra en la conversación cuando la búsqueda está ligada a la analítica. Si tu fuente de verdad son eventos, logs, trazas o métricas, ClickHouse mantiene en un único motor SQL la distancia vectorial, el filtrado, la agregación y una indexación de texto completo seria. No es una base de datos vectorial especializada, pero a menudo es la respuesta aburrida y correcta para la recuperación analítica.

Los vectores dispersos permiten obtener una coincidencia de palabras clave con la calidad de BM25 dentro de un índice vectorial, sin ejecutar un motor de texto completo separado. Qdrant y Elasticsearch tienen implementaciones especialmente maduras en este ámbito. Si la búsqueda híbrida es crítica y una arquitectura de dos sistemas no es negociable, eso es lo que debes buscar: compatibilidad con vectores dispersos.

Elige un almacén según la carga de trabajo


No incrustes identificadores y esperes coincidencias exactas

No uses la búsqueda vectorial como búsqueda de texto difusa para cosas que tienen una respuesta correcta.

«Busca el usuario cuyo email es dan@example.com» no es un problema de búsqueda vectorial. «Busca el pedido con el ID ORD-12345» tampoco. Incrustar ORD-12345 y buscar por similitud coseno devolverá algo, pero puede ser incorrecto. Un identificador tiene una respuesta correcta. Una coincidencia aproximada para un identificador es un bug.

La búsqueda vectorial devuelve lo más similar de tu conjunto de datos, incluso cuando nada es realmente relevante. No sabe detectar cuándo no existe una buena respuesta. Eso está bien para documentos relacionados. Es un problema serio en la búsqueda exacta de registros, donde una respuesta incorrecta dada con confianza es peor que un resultado vacío.

Lo mismo se aplica en la otra dirección: no uses FTS para consultas en las que el usuario está describiendo un concepto. «Artículos sobre cómo tomar decisiones difíciles bajo incertidumbre» no contiene palabras clave fiables. FTS devolverá ruido o no devolverá nada. Usa la herramienta adecuada para la forma de la consulta.


Construye la búsqueda alrededor de la forma de la consulta

La mayoría de los sistemas de búsqueda en producción necesitan más de una capa:

No son herramientas que compitan entre sí. Son complementarias. Un sistema de búsqueda bien construido elige la capa adecuada para cada forma de consulta y, cuando se solapan varias formas, ejecuta varias capas y fusiona los resultados.

Los equipos que lanzan buenas funciones de búsqueda entienden la pila completa. Los que no, recurren a una base de datos vectorial, incrustan todo y luego se preguntan por qué las búsquedas exactas a veces devuelven el registro equivocado.