Vai al contenuto principale

Hybrid Search: Combining Vector and Keyword Queries in MongoDB

Learn about hybrid search and how to utilize it in MongoDB.
Aggiornato 29 set 2026  · 6 min leggi

Scopri con l'IA

ChatGPTClaudePerplexity

A volte, la semplice ricerca full-text o la sola ricerca vettoriale non bastano per interrogare correttamente un database e ottenere i risultati che cerchi. La combinazione di entrambe è fantastica quando uno sviluppatore lavora con grandi quantità di dati multimodali e non strutturati che trarrebbero beneficio da entrambi i tipi di ricerca. Questo è noto come ricerca ibrida e offre agli sviluppatori un’ottima soluzione a una sfida complessa. 

Che cos’è esattamente la ricerca ibrida? 

Per capire bene la ricerca ibrida, dobbiamo prima capire cos’è la ricerca full-text. 

La ricerca full-text è un modo di cercare che confronta i termini letterali della tua query con i documenti. Questo tipo di ricerca tradizionale è in realtà quello con cui molti sviluppatori hanno molta familiarità.

Per esempio, se cerchi “caffetteria carina con tavoli all’aperto”, il motore di ricerca cercherà quelle esatte parole all’interno del database. In poche parole, la ricerca full-text è estremamente precisa ed efficiente, ma non funziona bene se vuoi ottenere gli stessi risultati cercando sinonimi, parafrasi o anche in caso di un refuso nella query. 

La ricerca vettoriale, invece, converte tutti i dati in numeri, o embedding. Quindi, invece di abbinare parole esatte, la ricerca vettoriale confronta il significato semantico della tua query con i documenti memorizzati nel database. 

Cercando “caffetteria carina con tavoli all’aperto” potrebbero comparire “pasticceria e caffè all’esterno”, anche se non usano le stesse parole. La ricerca vettoriale non è solo semantica; è anche molto flessibile, ma a volte può restituire risultati troppo ampi rispetto alla query specificata. 

Dove entra in gioco la ricerca ibrida? Combina sia la ricerca full-text sia la ricerca vettoriale. Ciò significa che gli sviluppatori possono sfruttare non solo l’intelligenza semantica dei vettori, ma anche mantenere le caratteristiche di filtro molto precise della ricerca full-text. È davvero il meglio di entrambi i mondi. Questo è super utile quando si lavora con grandi dataset non strutturati. 

Perché la ricerca ibrida è importante 

La ricerca ibrida è utile in molte applicazioni reali, tra cui (ma non solo) e-commerce, sanità e anche recruiting. 

Nell’e-commerce, immagina di accedere al tuo sito preferito e cercare “sedia da scrivania comoda sotto $100”. Con la ricerca vettoriale, vedrai elementi semanticamente simili (come sedie da ufficio ergonomiche), mentre la ricerca full-text si concentra sulla parola “sedia” e aiuta a far rispettare il prezzo. 

Nel recruiting, se un recruiter cerca tra i CV “ingegnere con esperienza in NLP”, la ricerca ibrida è in grado di catturare sia “natural language processing” sia la parola chiave esatta “ingegnere”.

Questo significa che puoi ottenere risultati più pertinenti e affidabili rispetto a usare ciascun approccio da solo. 

Ricerca ibrida in MongoDB

Vediamo come eseguire la ricerca ibrida in MongoDB Atlas. Per seguire con successo questo tutorial, ti serviranno alcuni prerequisiti: 

  1. Un account MongoDB Atlas  
  2. Un cluster MongoDB Atlas free tier
  3. mongosh scaricato nel tuo terminale

In questo tutorial, ci concentreremo sulla collezione embedded movies nel nostro database sample_mflix e seguiremo questo tutorial sulla ricerca ibrida $rankFusion, con alcune precisazioni. 

Sebbene il nuovo $rankFusion operator sia disponibile nei cluster versione 8.1+ e renda la ricerca ibrida eccezionalmente più semplice in MongoDB, è ancora in Public Preview e i cluster free tier sono automaticamente alla versione 8.0. Quindi seguiremo questo tutorial, apporteremo un paio di modifiche e arriveremo al risultato.

Esegui il provisioning del cluster

Durante il provisioning del cluster, assicurati di scaricare il dataset sample_mflix. È il dataset con cui lavoreremo per tutto il tutorial. Ci concentriamo sulla collezione sample_mflix.embedded_movies. 

Controlla rapidamente di avere mongosh installato.

mongosh --version

Per questo tutorial, sto usando la 2.4.2. 

Ora, connettiti al tuo cluster MongoDB Atlas:

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

Ti verrà richiesto di inserire la password e, una volta connesso, vedrai qualcosa del genere:

Ora possiamo connetterci al nostro database. Esegui il comando:

use sample_mflix

L’output sarà: 

switched to db sample_mflix

Crea i tuoi indici

Possiamo procedere e creare entrambi gli indici necessari per questo tutorial. Sono il nostro indice vettoriale e l’indice di ricerca full-text. Tieni presente che stiamo creando entrambi questi indici sulla collezione embedded_movies. 

Indice vettoriale:

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

Indice di ricerca full-text:

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

Controlla bene nel tuo cluster MongoDB Atlas che gli indici siano pronti:

Interroga il nostro database

Ora vogliamo interrogare i dati nella collezione sample_mflix.embedded_movies per “star wars” nel campo plot_embedding_voyage_3_large. 

Seguendo il tutorial, dato che non dobbiamo usare API, possiamo salvare tutti gli embedding necessari in un file separato chiamato query_embeddings.js. 

Ora possiamo caricare gli embedding da usare nella query. Esegui quanto segue:

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

Per assicurarti che gli embedding siano stati caricati correttamente, esegui il comando:

STAR_WARS_EMBEDDING.length

Un output di 2048 è corretto. 

Pipeline di aggregazione

Ora possiamo creare una pipeline di aggregazione per la ricerca ibrida. Tieni presente che ci sono alcune limitazioni e motivazioni dietro al motivo per cui abbiamo dovuto impostare la pipeline in questo modo. 

Come detto sopra, la prima è che, sebbene esista $rankFusion in MongoDB Atlas, è attualmente in Public Preview e richiede un cluster 8.0 o superiore. Con un cluster free tier, al momento non puoi usare $rankFusion. Questo complica un po’ le cose, perché MongoDB Atlas non fonderà nativamente per noi i ranking testuali e vettoriali. Significa che dobbiamo fare una nostra fusione, ovvero un blend ponderato delle due liste ordinate. 

Anche il posizionamento degli stage nelle pipeline di aggregazione è rigido:

  • $search deve essere il primo stage della pipeline. 
  • $vectorSearch deve essere l’inizio di una pipeline e non può stare dentro $facet.

Una soluzione? $vectorSearch può essere il primo stage della nostra sotto-pipeline dentro $unionWith, dato che questa sotto-pipeline è considerata una pipeline a sé. 

Per questo, dobbiamo iniziare con $search per i risultati full-text così da mantenere il loro punteggio, e poi usare $unionWith come seconda mini-pipeline che inizia con $vectorSearch in modo che anche questo mantenga il suo punteggio. 

Poi dobbiamo effettuare il group per _id così da non avere duplicati e usare il meglio dei nostri termini $search e $vectorSearch. 

Una volta fatto questo, dobbiamo calcolare la ricerca ibrida, ovvero il meglio del nostro $search, il meglio del nostro $vectorSearch, moltiplicato per un peso a nostra scelta (io ho scelto 0,35), e poi ordinare di conseguenza. 

Il peso determina quanta influenza ha la ricerca vettoriale rispetto alla ricerca full-text nei risultati finali. 

La nostra formula ibrida è: hybrid_score = text_score + (vector_score x weight). Quindi, un peso più alto (ad es. 0,7-1,0) significa che la ricerca vettoriale prevale e quindi dà priorità alla similarità semantica. 

Un peso più basso (0,1-0,3), invece, significa che prevale la ricerca full-text e si dà priorità alle corrispondenze esatte delle parole chiave. 

Copia e incolla questa pipeline di aggregazione nella finestra del terminale:

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()

Ecco il nostro output:

  {
    _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.

Argomenti
MongoDB
Database vettoriali

Top DataCamp Courses

{count, plural, one {Corso} other {Corsi}}

Introduzione a MongoDB in Python

{hours} ore
24.4K
Impara a gestire e analizzare dati strutturati in modo flessibile con MongoDB.
Vedi i dettagliRight Arrow
Inizia Il Corso
Mostra altroRight Arrow
Correlato

{count, plural, one {blog} other {blogs}}

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

{count, plural, one {blog} other {blogs}}

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

{count, plural, one {blog} other {blogs}}

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Mostra AltroMostra Altro