Ana içeriğe atla

Hybrid Search: Combining Vector and Keyword Queries in MongoDB

Learn about hybrid search and how to utilize it in MongoDB.
Güncel 3 Eki 2026  · 6 dk. oku

Yapay Zeka ile Keşfedin

ChatGPTClaudePerplexity

Bazen, yalnızca basit tümce araması ya da sadece vektör araması tek başına bir veritabanında doğru şekilde sorgu çalıştırmak ve aradığınız sonuçları almak için yeterli değildir. Her ikisinin kombinasyonu, geliştiricinin her iki arama türünden de fayda görecek büyük miktarda çok modlu, yapılandırılmamış verilerle uğraştığı durumlarda harikadır. Buna hibrit arama denir ve geliştiricilere zorlu bir sorun için mükemmel bir çözüm sunar. 

Hibrit Arama Tam Olarak Nedir? 

Hibrit aramayı doğru anlamak için önce tümce aramasının ne olduğunu anlamamız gerekir. 

Tümce araması, sorgunuzdaki sözcükleri belgelerinizdeki ifadelerle birebir eşleştiren bir arama yöntemidir. Bu geleneksel arama türü, aslında birçok geliştiricinin çok iyi bildiği bir yaklaşımdır.

Örneğin, “dış mekân oturma alanı olan sevimli kafe” araması yaparsanız, arama motoru veritabanında tam olarak bu sözcükleri arar. Kısacası, tümce araması son derece hassas ve verimlidir; ancak eşanlamlılar, yeniden ifade etme (paraphrasing) ya da sorgunuzda yazım hatası olduğunda aynı sonuçları elde etmek istiyorsanız iyi çalışmaz. 

Vektör araması ise tüm verileri sayılara, yani gömlemelere dönüştürür. Yani, tam sözcükleri eşleştirmek yerine vektör araması, sorgunuzun anlamsal içeriğini veritabanınızda saklanan belgelerle karşılaştırır. 

“Dış mekân oturma alanı olan sevimli kafe” araması, birebir aynı sözcükleri kullanmasa bile “dışarıda hamur işleri ve kahve” gibi sonuçlar getirebilir. Vektör araması sadece anlamsaldır ve oldukça esnektir; ancak bazen belirtilen sorguya göre fazla geniş sonuçlar döndürebilir. 

Peki hibrit arama nerede devreye giriyor? Hem tümce aramasını hem de vektör aramasını birleştirir. Bu, geliştiricilerin vektörlerin anlamsal zekâsından yararlanırken aynı zamanda tümce aramasının son derece hassas filtreleme özelliklerini de koruyabileceği anlamına gelir. Gerçekten de iki dünyanın en iyisini sunar. Büyük, yapılandırılmamış veri kümeleriyle çalışırken geliştiriciler için son derece kullanışlıdır. 

Hibrit Aramanın Önemi 

Hibrit arama; e-ticaret, sağlık hizmetleri ve hatta işe alım gibi birçok gerçek yaşam uygulamasında (bunlarla sınırlı olmamak üzere) faydalıdır. 

E-ticarette, favori web sitenize girip “100 doların altında rahat çalışma koltuğu” aradığınızı düşünün. Vektör aramasıyla, anlamsal olarak benzer öğeleri (örneğin ergonomik ofis koltukları) görürsünüz; tümce araması ise “koltuk” sözcüğüne odaklanır ve fiyat noktasını uygulatmaya yardımcı olur. 

İşe alımda, bir işe alım uzmanı “NLP deneyimli mühendis” için özgeçmişlerde arama yapıyorsa, hibrit arama hem “doğal dil işleme” ifadesini hem de “mühendis” anahtar kelimesini yakalayabilir.

Bu da tek başına herhangi bir yaklaşımı kullanmaya kıyasla daha ilgili ve güvenilir sonuçlar alabileceğiniz anlamına gelir. 

MongoDB’de Hibrit Arama

MongoDB Atlas’ta hibrit aramanın nasıl yapılacağını gözden geçirelim. Bu eğitimde başarılı olmak için birkaç önkoşula ihtiyacınız olacak: 

  1. Bir MongoDB Atlas hesabı  
  2. Bir ücretsiz katman MongoDB Atlas kümesi
  3. mongosh’un terminalinize indirilmiş olması

Bu eğitimde, sample_mflix veritabanımızdaki gömülü filmler koleksiyonuna odaklanacağız ve birkaç nüansla birlikte şu $rankFusion hibrit arama eğitimini takip edeceğiz. 

Yeni $rankFusion operatörü 8.1+ sürümlü kümelerde kullanılabilir ve MongoDB’de hibrit aramayı son derece kolaylaştırır; ancak hâlâ Genel Önizleme aşamasındadır ve ücretsiz katman kümeleri otomatik olarak 8.0 sürümündedir. Bu nedenle bu eğitimi takip edecek, birkaç şeyi değiştirecek ve güçlü bir şekilde tamamlayacağız.

Kümenizi hazırlayın

Kümenizi sağlarken lütfen sample_mflix veri setini indirdiğinizden emin olun. Eğitim boyunca bu veri setiyle çalışacağız. Odaklandığımız koleksiyon sample_mflix.embedded_movies. 

Hızlıca mongosh’un yüklü olduğunu kontrol edin.

mongosh --version

Bu eğitim için 2.4.2 kullanıyorum. 

Şimdi MongoDB Atlas kümenize bağlanın:

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

Şifre istenecektir ve bağlandıktan sonra ekran şöyle görünecektir:

Artık veritabanımıza bağlanabiliriz. Komutu çalıştırın:

use sample_mflix

Çıktı şu olacaktır: 

switched to db sample_mflix

Dizinlerinizi oluşturun

Bu eğitim için ihtiyaç duyduğumuz iki dizini oluşturabiliriz. Bunlar vektör dizinimiz ve tümce araması dizinimizdir. Her iki dizini de embedded_movies koleksiyonumuz üzerinde oluşturduğumuzu unutmayın. 

Vektör dizini:

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

Tümce araması dizini:

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

MongoDB Atlas kümeniz içinde dizinlerin hazır olduğunu tekrar kontrol edin:

Veritabanımızı sorgulayalım

Şimdi, sample_mflix.embedded_movies koleksiyonumuzdaki verileri plot_embedding_voyage_3_large alanında “star wars” için sorgulamak istiyoruz. 

Eğitimi takip ederek, herhangi bir API kullanmak zorunda olmadığımız için ihtiyaç duyduğumuz tüm gömlemeleri query_embeddings.js adlı ayrı bir dosyaya kaydedebiliriz. 

Artık sorguda kullanmak üzere gömlemelerimizi yükleyebiliriz. Şunları çalıştırın:

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

Gömlemelerin başarıyla yüklendiğini doğrulamak için şu komutu çalıştırın:

STAR_WARS_EMBEDDING.length

2048 çıktısı doğrudur. 

Toplama (aggregation) ardışık düzeni

Artık hibrit arama için bir toplama ardışık düzeni oluşturabiliriz. Lütfen bu şekilde yaklaşmamızın arkasında birkaç sınırlama ve gerekçe olduğunu aklınızda bulundurun. 

Yukarıda belirtildiği gibi, MongoDB Atlas’ta $rankFusion olsa da şu anda Genel Önizleme aşamasındadır ve 8.0 veya üzeri bir kümeye ihtiyacınız vardır. Ücretsiz katman kümesinde şu anda $rankFusion kullanamazsınız. Bu durum işleri biraz karmaşıklaştırır çünkü MongoDB Atlas metin ve vektör sıralamalarını yerel olarak birleştirmez. Bu da kendi füzyonumuzu, yani iki sıralı listenin ağırlıklı harmanını yapmamız gerektiği anlamına gelir. 

Toplama ardışık düzenlerinde aşama yerleşimleri de katıdır:

  • $search, ardışık düzenin ilk aşaması olmalıdır. 
  • $vectorSearch bir ardışık düzenin başlangıcında olmalı ve $facet içinde bulunamaz.

Geçici çözüm? $vectorSearch, $unionWith içindeki alt ardışık düzenimizin ilk aşaması olabilir; çünkü bu alt ardışık düzen kendi başına bir ardışık düzen olarak kabul edilir. 

Bundan dolayı, puanlarını korumak için tümce araması sonuçlarımızda $search ile başlamalı ve ardından $vectorSearch ile başlayan ikinci bir mini ardışık düzen olarak $unionWith kullanmalıyız ki kendi puanını da korusun. 

Sonrasında, yinelenenleri önlemek ve $search ile $vectorSearch terimlerimizin her birinden en iyisini kullanmak için _id’ye göre gruplaymamız gerekir. 

Bundan sonra hibrit aramayı formüle etmemiz gerekir: $search’ten gelen en iyi sonuç, $vectorSearch’ten gelen en iyi sonuç ve ardından seçtiğimiz bir ağırlıkla (ben 0,35 seçtim) çarpılıp buradan sıralanması. 

Ağırlık, nihai sonuçlarda vektör aramasının tümce aramasına kıyasla ne kadar etkili olacağını belirler. 

Hibrit formülümüz: hybrid_score = text_score + (vector_score x weight). Yani daha yüksek bir ağırlık (ör. 0,7-1,0) vektör aramasının baskın olduğu ve anlamsal benzerliğin önceliklendirildiği anlamına gelir. 

Öte yandan daha düşük bir ağırlık (0,1-0,3), tümce aramasının baskın olduğu ve tam anahtar kelime eşleşmelerini önceliklendirmeye yardımcı olduğu anlamına gelir. 

Bu toplama ardışık düzenini terminal pencerenize kopyalayıp yapıştırın:

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

Çıktımız şöyle:

  {
    _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
  }
]).toArray()

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.

Konular
MongoDB
Vektör Veritabanları

Top DataCamp Courses

Kurs

Python ile MongoDB'ye Giriş

3 sa
24.4K
MongoDB ile esnek yapılandırılmış verileri işlemeyi ve analiz etmeyi öğrenin.
Ayrıntıları GörüntüleRight Arrow
Kursa Başla
Devamını GörRight Arrow
İlgili

blog

Hızlı Sevkiyat İçin Pratik Vibe Kodlama Teknoloji Yığını

Ön uç, arka uç, veritabanları, kimlik doğrulama, depolama, e-posta, test, dağıtım ve izleme için en iyi araçları keşfedin.
Abid Ali Awan's photo

Abid Ali Awan

14 dk.

blog

2026’da En Popüler 40 Yazılım Mühendisi Mülakat Sorusu

Algoritmalar, sistem tasarımı ve davranışsal senaryoları kapsayan bu temel sorularla teknik mülakat sürecine hakim olun. Uzman cevapları, kod örnekleri ve kanıtlanmış hazırlık stratejileri edinin.
Dario Radečić's photo

Dario Radečić

15 dk.

Eğitim

Python'da Listeyi String'e Nasıl Dönüştürürsünüz

Bu hızlı eğitimde, Python'da bir listeyi string'e nasıl dönüştüreceğinizi öğrenin.
Adel Nehme's photo

Adel Nehme

Eğitim

.gitignore Nasıl Kullanılır: Örneklerle Pratik Bir Giriş

Git deponuzu temiz tutmak için .gitignore’u nasıl kullanacağınızı öğrenin. Bu eğitim; temelleri, yaygın kullanım durumlarını ve başlamanıza yardımcı olacak pratik örnekleri kapsar!
Kurtis Pykes 's photo

Kurtis Pykes

8 dk.

Devamını GörDevamını Gör