Ir al contenido principal

Hybrid Search: Combining Vector and Keyword Queries in MongoDB

Learn about hybrid search and how to utilize it in MongoDB.
Actualizado 17 sept 2026  · 6 min leer

Explorar con IA

ChatGPTClaudePerplexity

A veces, la búsqueda de texto completo por sí sola o solo la búsqueda vectorial no bastan para consultar correctamente una base de datos y obtener los resultados que buscas. La combinación de ambas es ideal cuando un desarrollador trabaja con grandes volúmenes de datos multimodales y no estructurados que se benefician de los dos tipos de búsqueda. A esto se le llama búsqueda híbrida, y ofrece a los desarrolladores una gran solución para un reto complejo. 

¿Qué es exactamente la búsqueda híbrida? 

Para entender bien la búsqueda híbrida, primero tenemos que comprender qué es la búsqueda de texto completo. 

La búsqueda de texto completo compara términos literales de tu consulta con los documentos. Este enfoque tradicional es el que muchos desarrolladores conocen bien.

Por ejemplo, si buscas «cafetería mona con terraza», el motor buscará esas palabras exactas en la base de datos. En pocas palabras, la búsqueda de texto completo es muy precisa y eficiente, pero no funciona bien si quieres obtener los mismos resultados usando sinónimos, parafraseando o si tu consulta tiene una errata. 

La búsqueda vectorial, en cambio, convierte todos los datos en números, o embeddings. En lugar de hacer coincidir palabras exactas, la búsqueda vectorial compara el significado semántico de tu consulta con los documentos almacenados en la base de datos. 

Si buscas «cafetería mona con terraza», puede devolverte «pasteles y café al aire libre», aunque no use las mismas palabras. La búsqueda vectorial no solo es semántica; también es muy flexible, pero a veces puede devolver resultados demasiado amplios para la consulta indicada. 

Entonces, ¿dónde entra la búsqueda híbrida? Combina la búsqueda de texto completo y la búsqueda vectorial. Así, los desarrolladores aprovechan la inteligencia semántica de los vectores y, al mismo tiempo, conservan los filtros precisos de la búsqueda de texto completo. Es, literalmente, lo mejor de ambos mundos. Y es especialmente útil al trabajar con grandes conjuntos de datos no estructurados. 

Por qué importa la búsqueda híbrida 

La búsqueda híbrida es útil en muchas aplicaciones reales, como comercio electrónico, salud o incluso selección de personal. 

En e-commerce, imagina entrar en tu web favorita y buscar «silla de escritorio cómoda por menos de 100 $». Con la búsqueda vectorial verás artículos semánticamente similares (por ejemplo, sillas ergonómicas), mientras que la búsqueda de texto completo se centra en la palabra «silla» y ayuda a aplicar el límite de precio. 

En selección, si una persona reclutadora busca en currículos «ingeniero con experiencia en NLP», la búsqueda híbrida capta tanto «natural language processing» como la palabra clave exacta «engineer».

Esto significa que obtendrás resultados más relevantes y fiables que usando cualquiera de los dos enfoques por separado. 

Búsqueda híbrida en MongoDB

Veamos cómo hacer búsqueda híbrida en MongoDB Atlas. Para seguir este tutorial con éxito, necesitarás algunos requisitos previos: 

  1. Una cuenta de MongoDB Atlas  
  2. Un clúster de MongoDB Atlas de la capa gratuita
  3. mongosh instalado en tu terminal

En este tutorial nos centraremos en la colección de películas embebidas del conjunto de datos sample_mflix, y seguiremos este tutorial de búsqueda híbrida con $rankFusion, con algunos matices. 

Aunque el nuevo operador $rankFusion está disponible en clústeres con la versión 8.1+ y facilita muchísimo la búsqueda híbrida en MongoDB, sigue en Public Preview y los clústeres de la capa gratuita están en la versión 8.0. Así que seguiremos este tutorial, ajustaremos un par de cosas y llegaremos al objetivo.

Provisiona tu clúster

Al crear tu clúster, asegúrate de descargar el conjunto de datos sample_mflix. Es el que usaremos durante todo el tutorial. Nos centraremos en la colección sample_mflix.embedded_movies

Comprueba rápidamente que tienes mongosh instalado.

mongosh --version

Para este tutorial, estoy usando la 2.4.2. 

Ahora, conéctate a tu clúster de MongoDB Atlas:

mongosh "mongodb+srv://<yourclusterhere>.mongodb.net/" --apiVersion 1 --username <yourusername> 

Se te pedirá la contraseña y, una vez conectado, verás algo así:

Ahora podemos conectarnos a nuestra base de datos. Ejecuta el comando:

use sample_mflix

La salida será: 

switched to db sample_mflix

Crea tus índices

Vamos a crear los dos índices que necesitamos para este tutorial: el índice vectorial y el índice de texto completo. Ten en cuenta que ambos índices los creamos en la colección embedded_movies

Índice vectorial:

db.embedded_movies.createSearchIndex(
  "hybrid-vector-search",
  "vectorSearch",
  {
    fields: [
      { type: "vector", path: "plot_embedding_voyage_3_large", numDimensions: 2048, similarity: "dotProduct" }
    ]
  }
)

Índice de texto completo:

db.embedded_movies.createSearchIndex(
  "hybrid-full-text-search",
  "search",
  { mappings: { dynamic: true } }
)

Verifica en tu clúster de MongoDB Atlas que los índices estén listos:

Consulta nuestra base de datos

Ahora queremos consultar los datos de sample_mflix.embedded_movies para «star wars» en el campo plot_embedding_voyage_3_large

Siguiendo el tutorial, como no tenemos que usar APIs, podemos guardar todos los embeddings necesarios en un archivo aparte llamado query_embeddings.js

Ahora podemos cargar los embeddings para usarlos en la consulta. Ejecuta lo siguiente:

load('/Users/<PATH NAME>/query_embeddings.js')
const queryVec = STAR_WARS_EMBEDDING

Para comprobar que los embeddings se han cargado correctamente, ejecuta:

STAR_WARS_EMBEDDING.length

Una salida de 2048 es correcta. 

Pipeline de agregación

Ahora podemos crear un pipeline de agregación para la búsqueda híbrida. Ten en cuenta que hay algunas limitaciones y razones por las que abordamos el pipeline de esta manera. 

Como hemos dicho, aunque $rankFusion está en MongoDB Atlas, actualmente está en Public Preview y necesitas un clúster 8.0 o superior. Con la capa gratuita no puedes usar $rankFusion por ahora. Esto complica un poco las cosas porque Atlas no fusionará de forma nativa las clasificaciones de texto y vector. Así que debemos hacer nuestra propia fusión, o una mezcla ponderada de ambas listas ordenadas. 

La colocación de etapas en los pipelines de agregación también es estricta:

  • $search debe ser la primera etapa del pipeline. 
  • $vectorSearch tiene que ir al inicio de un pipeline y no puede estar dentro de $facet.

¿La solución? $vectorSearch puede ser la primera etapa de un subpipeline dentro de $unionWith, ya que ese subpipeline se considera un pipeline independiente. 

Por ello, debemos empezar con $search para que los resultados de texto completo conserven su puntuación, y usar $unionWith como un mini-pipeline que comienza con $vectorSearch para que también conserve su puntuación. 

Luego necesitamos agrupar por _id para evitar duplicados y usar lo mejor de $search y $vectorSearch

Después, calculamos la búsqueda híbrida: lo mejor de $search, lo mejor de $vectorSearch, multiplicado por un peso a elegir (yo he elegido 0.35) y ordenamos a partir de ahí. 

El peso determina cuánto influye la búsqueda vectorial frente a la búsqueda de texto completo en los resultados finales. 

Nuestra fórmula híbrida es: hybrid_score = text_score + (vector_score x weight). Un peso alto (p. ej., 0.7-1.0) hace que predomine la búsqueda vectorial y, por tanto, la similitud semántica. 

Un peso bajo (0.1-0.3), en cambio, hace que predomine la búsqueda de texto completo y prioriza las coincidencias exactas de palabras clave. 

Copia y pega este pipeline de agregación en tu terminal:

const WEIGHT = 0.35;

db.embedded_movies.aggregate([
// Stage 1: full-text search
  { $search: { index: "hybrid-full-text-search", text: { query: "star wars", path: ["title","plot"] } } },
  { $set: { t: { $meta: "searchScore" } } },
  { $project: { _id: 1, title: 1, plot: 1, t: 1 } },
// Stage 2: Union with vector search
  { $unionWith: {
      coll: "embedded_movies",
      pipeline: [
// Vector search subpipeline
        { $vectorSearch: {
            index: "hybrid-vector-search",
            path: "plot_embedding_voyage_3_large",
            queryVector: queryVec,
            numCandidates: 200,
            limit: 150
        }},
        { $project: { _id: 1, title: 1, plot: 1, v: { $meta: "vectorSearchScore" } } }
      ]
  }},
// Stage 3: Combine and rank results
  { $group: { _id: "$_id", title: { $first: "$title" }, plot: { $first: "$plot" }, t: { $max: "$t" }, v: { $max: "$v" } } },
  { $set: { h: { $add: [ { $ifNull: ["$t", 0] }, { $multiply: [ { $ifNull: ["$v", 0] }, WEIGHT ] } ] } } },
  { $sort: { h: -1 } },
  { $limit: 20 }
]).toArray()

Este es el resultado:

  {
    _id: ObjectId('573a139af29313caabcf124d'),
    title: 'Star Wars: Episode III - Revenge of the Sith',
    plot: 'As the Clone Wars near an end, the Sith Lord Darth Sidious steps out of the shadows, at which time Anakin succumbs to his emotions, becoming Darth Vader and putting his relationships with Obi-Wan and Padme at risk.',
    t: 4.957413673400879,
    v: 0.756283700466156,
    h: 5.2221129685640335
  },
  {
    _id: ObjectId('573a13a6f29313caabd17d08'),
    title: 'Star',
    plot: 'The Driver now carries an arrogant rock star who is visiting a major city (not Pittsburgh as earlier believed). Played by Madonna, this title character wants to get away from her bodyguards...',
    t: 5.151784420013428,
    v: null,
    h: 5.151784420013428
  },
  {
    _id: ObjectId('573a1397f29313caabce8cdb'),
    title: 'Star Wars: Episode VI - Return of the Jedi',
    plot: 'After rescuing Han Solo from the palace of Jabba the Hutt, the rebels attempt to destroy the second Death Star, while Luke struggles to make Vader return from the dark side of the Force.',
    t: 4.726564407348633,
    v: 0.7782549858093262,
    h: 4.998953652381897
  },
  {
    _id: ObjectId('573a13aef29313caabd2da15'),
    title: 'Star Runner',
    plot: 'Get ready for the ultimate martial arts competition, where anything goes and lives are bought and sold. Tank is the celebrated Champion Star Runner and is deemed invincible among the ...',
    t: 4.702453136444092,
    v: 0.696668267250061,
    h: 4.9462870299816135
  },
  {
    _id: ObjectId('573a13c0f29313caabd62f62'),
    title: 'Star Wars: The Clone Wars',
    plot: 'Anakin Skywalker and Ahsoka Tano must rescue the kidnapped son of Jabba the Hutt, but political intrigue complicates their mission.',
    t: 4.537533760070801,
    v: 0.7561323642730713,
    h: 4.802180087566375
  },
  {
    _id: ObjectId('573a1397f29313caabce6f53'),
    title: 'Message from Space',
    plot: 'In this Star Wars take-off, the peaceful planet of Jillucia has been nearly wiped out by the Gavanas, whose leader takes orders from his mother (played a comic actor in drag) rather than ...',
    t: 4.401333808898926,
    v: 0.7913960218429565,
    h: 4.678322416543961
  },
  {
    _id: ObjectId('573a139df29313caabcfa90b'),
    title: 'Message from Space',
    plot: 'In this Star Wars take-off, the peaceful planet of Jillucia has been nearly wiped out by the Gavanas, whose leader takes orders from his mother (played a comic actor in drag) rather than ...',
    t: 4.401333808898926,
    v: 0.7913960218429565,
    h: 4.678322416543961
  },
  {
    _id: ObjectId('573a1398f29313caabce9851'),
    title: 'Gymkata',
    plot: 'Johnathan Cabot is a champion gymnast. In the tiny, yet savage, country of Parmistan, there is a perfect spot for a "star wars" site. For the US to get this site, they must compete in the ...',
    t: 4.284864902496338,
    v: 0.7193170189857483,
    h: 4.53662585914135
  },
  {
    _id: ObjectId('573a1397f29313caabce68f6'),
    title: 'Star Wars: Episode IV - A New Hope',
    plot: "Luke Skywalker joins forces with a Jedi Knight, a cocky pilot, a wookiee and two droids to save the universe from the Empire's world-destroying battle-station, while also attempting to rescue Princess Leia from the evil Darth Vader.",
    t: 2.9629626274108887,
    v: 0.7987099885940552,
    h: 3.242511123418808
  },
  {
    _id: ObjectId('573a139af29313caabcf0f5f'),
    title: 'Star Wars: Episode I - The Phantom Menace',
    plot: 'Two Jedi Knights escape a hostile blockade to find allies and come across a young boy who may bring balance to the Force, but the long dormant Sith resurface to reclaim their old glory.',
    t: 2.9629626274108887,
    v: 0.7771433591842651,
    h: 3.2349628031253816
  },
  {
    _id: ObjectId('573a1397f29313caabce77d9'),
    title: 'Star Wars: Episode V - The Empire Strikes Back',
    plot: 'After the rebels have been brutally overpowered by the Empire on their newly established base, Luke Skywalker takes advanced Jedi training with Master Yoda, while his friends are pursued by Darth Vader as part of his plan to capture Luke.',
    t: 2.7174296379089355,
    v: 0.7810181975364685,
    h: 2.9907860070466996
  },
  {
    _id: ObjectId('573a139af29313caabcf1258'),
    title: 'Star Wars: Episode II - Attack of the Clones',
    plot: 'Ten years after initially meeting, Anakin Skywalker shares a forbidden romance with Padmè, while Obi-Wan investigates an assassination attempt on the Senator and discovers a secret clone army crafted for the Jedi.',
    t: 2.7174296379089355,
    v: 0.7400004267692566,
    h: 2.9764297872781755
  },
  {
    _id: ObjectId('573a1394f29313caabcdf65b'),
    title: 'Ugetsu',
    plot: 'A fantastic tale of war, love, family and ambition set in the midst of the Japanese Civil Wars of the sixteenth century.',
    t: 2.858368396759033,
    v: null,
    h: 2.858368396759033
  },
  {
    _id: ObjectId('573a13a4f29313caabd1137f'),
    title: 'S1m0ne',
    plot: "A producer's film is endangered when his star walks off, so he decides to digitally create an actress to substitute for the star, becoming an overnight sensation that everyone thinks is a real person.",
    t: 2.842216730117798,
    v: null,
    h: 2.842216730117798
  },
  {
    _id: ObjectId('573a13b8f29313caabd4c3c3'),
    title: 'Star Trek',
    plot: "The brash James T. Kirk tries to live up to his father's legacy with Mr. Spock keeping him in check as a vengeful, time-traveling Romulan creates black holes to destroy the Federation one planet at a time.",
    t: 2.577816963195801,
    v: 0.7295459508895874,
    h: 2.8331580460071564
  },
  {
    _id: ObjectId('573a13b5f29313caabd42e99'),
    title: 'Sars Wars',
    plot: "The fourth generation of the virus SARS is found in Africa! It's more dangerous and causes the patients to transform into bloodthirsty zombies. The virus quickly lands to Thailand, Dr. ...",
    t: 2.826810598373413,
    v: null,
    h: 2.826810598373413
  },
  {
    _id: ObjectId('573a13b5f29313caabd42e1b'),
    title: 'Sars Wars',
    plot: "The fourth generation of the virus SARS is found in Africa! It's more dangerous and causes the patients to transform into bloodthirsty zombies. The virus quickly lands to Thailand, Dr. ...",
    t: 2.826810598373413,
    v: null,
    h: 2.826810598373413
  }

As we can see, we have some results that are identical to our query, “star wars,” and other results that are clearly off of meaning.

Conclusion 

Congratulations! You have successfully completed hybrid search in MongoDB. While $rankFusion will simplify this process, this method shows a workaround while the operator is still in Public Preview. Through this tutorial, we have successfully incorporated both full-text search and vector search into one pipeline to retrieve the most optimal results for our given query. For more information on hybrid search in MongoDB, please refer to the MongoDB documentation. If you’re still getting up to speed with MongoDB, I recommend the Introduction to MongoDB in Python course.

MongoDB Hybrid Search FAQs

Do I need MongoDB 8.1 and `$rankFusion` to do hybrid search

No. On 8.0, you can actually fuse the scores yourself. Do this by running $search and $vectorSearch in two pipelines and combine them with $unionWith + $group and a weighted formula. On 8.1+, $rankFusion will do this for you.

What is hybrid search?

It’s combining full-text search (exact words) and vector search (meaning) for the most optimal results possible from a given query.

When should I use hybrid search?

Use hybrid search when your text is varied (synonyms, paraphrases, typos) but you still want exact terms.

How do I pick the weight I want to use?

It’s best practice to begin around 0.2-0.5. The lower is more for full-text search influence, and higher is for semantic influence. It’s important to tune the weight after testing and viewing the results provided.

Can hybrid search work with image and audio data?

Yes! As long as your data can be turned into vector embeddings and you can combine them with any specific wording constraints, you can perform hybrid search on a dataset.

Temas
MongoDB
Bases de datos vectoriales

Top DataCamp Courses

Curso

Introducción a MongoDB en Python

3 h
24.3K
Aprende a manipular y analizar datos estructurados de forma flexible con MongoDB.
Ver detallesRight Arrow
Iniciar Curso
Ver másRight Arrow
Relacionado

blog

Las 7 mejores bases de datos vectoriales en 2026

Una guía completa sobre las mejores bases de datos vectoriales. Domina el almacenamiento de datos de alta dimensión, descifra información no estructurada y aprovecha las incrustaciones vectoriales para aplicaciones de IA.
Moez Ali's photo

Moez Ali

14 min

blog

¿Qué es vector embedding? Una explicación intuitiva

Vector embedding refiere a representaciones numéricas de palabras o frases que captan sus significados y relaciones, ayudando a los modelos de aprendizaje automático a comprender el texto con mayor eficacia.

Tutorial

Tutorial de pgvector: Integrar la búsqueda vectorial en PostgreSQL

Descubre cómo mejorar PostgreSQL con capacidades de búsqueda vectorial utilizando pgvector. Este tutorial te guía a través de la instalación, las operaciones básicas y la integración con herramientas de IA.
Moez Ali's photo

Moez Ali

10 min

Tutorial

Guía de modelado de datos de MongoDB para aplicaciones de blogs

Aprende algunas posibilidades de modelado de datos que incluyen documentos anidados al diseñar un sistema de gestión de contenidos (CMS) o una aplicación de blog.
Nic Raboy's photo

Nic Raboy

Tutorial

Cómo utilizar GROUP BY y HAVING en SQL

Una guía intuitiva para descubrir los dos comandos SQL más populares para agregar filas de tu conjunto de datos
Eugenia Anello's photo

Eugenia Anello

6 min

Tutorial

Cómo hacer un VLOOKUP() con múltiples criterios

Domina el arte de utilizar VLOOKUP() con criterios múltiples en Excel. Explora técnicas avanzadas como las columnas de ayuda y la función ELEGIR().
Laiba Siddiqui's photo

Laiba Siddiqui

10 min

Ver MásVer Más