RAG 實戰筆記

向量資料庫與 MongoDB 差在哪?從一個同時用 Qdrant 和 MongoDB 的專案說起

2026-08-09 #RAG#Qdrant#向量資料庫#MongoDB#資料庫

「都是資料庫,為什麼 RAG 要特地用向量資料庫?MongoDB 不行嗎?」——這是我被問過、也曾自問過的問題。最好的回答方式不是抽象比較,而是看一個真實的架構:我的企業文件問答平台(上一篇介紹過)同時用了 Qdrant 和 MongoDB,兩者各司其職、誰也取代不了誰。這篇從「它們根本在回答不同的問題」講起,最後整理成何時該用哪個的判斷準則。

一、核心差異:兩種完全不同的「查詢」

先把最本質的差異放在最前面。

MongoDB 回答的問題是:「找出符合條件的資料。」

1
2
// 找出「業務部」所有「已完成」的任務
db.tasks.find({ department: "業務部", status: "done" })

這是精確匹配的世界:條件成立就回傳,不成立就不回傳,結果非黑即白。底層靠 B-tree 索引,本質上是排好序的目錄,查詢是「翻到那一頁」。

向量資料庫回答的問題是:「找出跟這個東西最『像』的資料。」

1
2
# 找出跟「員工請假要跑什麼流程」語意最接近的 20 個文件切塊
client.search(collection, query_vector=embed("員工請假要跑什麼流程"), limit=20)

這是相似度的世界:沒有「符合/不符合」,只有「多接近」。每筆資料是一個高維向量(我的專案用 1024 維),查詢是在這個空間裡找最近鄰。結果永遠是一個按距離排序的清單,第 1 名和第 20 名的差別只是遠近。

一句話總結:MongoDB 做的是「查找」(lookup),向量資料庫做的是「召回」(recall)。前者要的是準確命中,後者要的是語意涵蓋。

二、為什麼一般資料庫做不好向量搜尋?

「那我把向量存進 MongoDB 的欄位,查的時候自己算距離不就好了?」——可以,但會撞上兩堵牆。

第一堵牆:算距離不能用傳統索引。 B-tree 的前提是資料能排序(數字有大小、字串有字典序),但 1024 維向量之間只有「距離」沒有「順序」,B-tree 完全使不上力。不用索引的話就是暴力掃描:每次查詢跟全部向量算一次餘弦相似度——一萬筆還行,百萬筆每查一次都是災難。

第二堵牆:近似最近鄰(ANN)是門專門的學問。 向量資料庫的核心武器是 HNSW 這類 ANN 索引——用「多層跳躍圖」讓搜尋不用走訪全部節點就能找到近鄰,以極小的精度損失換取數量級的速度提升。這套索引的建構、維護、調參(精度與速度的權衡)是向量資料庫的看家本領。

此外還有 RAG 實戰很依賴的周邊能力,以我用的 Qdrant 為例:

  • 一個 collection 同時放 dense + sparse 兩種向量——上一篇講的混合檢索,原生支援
  • payload 過濾與向量搜尋同時做——「在『非機密』的切塊裡找最相似的」一次完成,這是我的權限系統的地基(下面細講)
  • 量化壓縮、分片、向量專用的記憶體管理

公平地說:傳統資料庫陣營正在追。MongoDB Atlas 有 Vector Search、PostgreSQL 有 pgvector,小規模場景已經夠用,「順手用現有的資料庫加向量欄位」是完全合理的起點。但截至目前,混合檢索、過濾效率、向量規模化這些硬仗,專用向量資料庫仍是更穩的選擇——尤其自架(不用雲服務)的時候,MongoDB 社群版並沒有向量搜尋能力。

三、真實架構:我的專案裡兩者怎麼分工

講理論不如看實戰。我的文件問答平台資料層長這樣:

資料庫 存什麼 角色
Qdrant 文件切塊的 dense/sparse 向量 + payload(原文、來源、切塊序號、機密等級) 檢索引擎:回答「哪些切塊跟問題最相關」
MongoDB 文件原始記錄、上傳任務狀態、對話歷史、使用者收藏、稽核紀錄 業務資料的家:回答「這份文件是誰上傳的」「這場對話說了什麼」
SQLite 帳號、角色、部門、權限 關聯式的權限模型(RBAC)
Redis 任務佇列、快取 背景工作的傳令兵

注意分工的邏輯:

Qdrant 是「可重建的索引」,MongoDB 是「事實的來源」。 向量庫裡的東西全部是從原始文件推導出來的——我的 ingest.py 甚至設計成每次重跑就清空重建整個 collection,方便「改切塊參數 → 重算 → 評測」的調校迴圈。敢這樣做正是因為向量庫裡沒有任何不可再生的資料。反過來,MongoDB 裡的對話歷史、稽核紀錄是事實本身,掉了就是掉了。這個「來源 vs 索引」的區分,是多資料庫架構最重要的心智模型。

各自發揮所長,而不是互相替代。 使用者問問題 → Qdrant 負責從幾萬個切塊裡召回最相關的 30 個;答案生成後 → 對話寫進 MongoDB;管理員要查「上週誰上傳了什麼文件」→ 純 MongoDB 條件查詢,向量庫完全不參與。硬要單邊包辦的話:MongoDB 做語意檢索做不動(自架版根本沒有),Qdrant 存對話歷史則是拿檢索引擎當業務資料庫用——payload 是給過濾用的,不是給你 CRUD 的。

權限在檢索層強制執行。 這是兩者合作最精彩的地方:每個切塊寫入 Qdrant 時都帶著 confidentiality(機密等級)payload;使用者查詢時,後端把他的權限範圍組成 Qdrant filter,向量搜尋只在他有權看的切塊中進行。沒權限的文件不是「檢索到了再過濾掉」,而是從一開始就不在搜尋範圍裡——不會漏答案位置、不會浪費召回名額、更不會在錯誤訊息裡洩漏機密文件的存在。這種「相似度搜尋 + 結構化過濾」一次完成的能力,正是向量資料庫相對於「自己算距離」的決定性優勢。

四、對照表:一次看懂

面向 MongoDB(文件資料庫) 向量資料庫(Qdrant 等)
回答的問題 符合條件的資料 語意最接近的資料
查詢結果 精確集合(符合/不符合) 排序清單(按距離遠近)
核心索引 B-tree HNSW 等 ANN 索引
資料單位 JSON 文件 向量 + payload
擅長 CRUD、聚合統計、業務邏輯 相似度搜尋、混合檢索、帶過濾的召回
不擅長 語意搜尋(自架版沒有) 交易、複雜聚合、當業務主資料庫
資料性質 事實來源(不可再生) 推導索引(可隨時重建)
在 RAG 中的角色 存文件記錄、對話、稽核 檢索引擎本體

五、判斷準則:你需要哪一個?

  • 只需要條件查詢、統計、業務資料 → MongoDB(或任何你熟的資料庫),跟向量無關。
  • 要做語意搜尋,資料量小(幾萬筆內)、已在用 MongoDB Atlas 或 PostgreSQL → 先用 Atlas Vector Search / pgvector,別為了技術潮流多養一個服務。
  • RAG 是核心功能,需要混合檢索、metadata 過濾、自架部署,或資料量會成長 → 專用向量資料庫。我選 Qdrant 的理由:docker compose 一行起服務、原生 dense+sparse 雙向量、filter 表達力強(權限系統直接建在上面)。
  • 做正經的系統 → 大概率跟我一樣兩個都要:向量庫當檢索引擎,一般資料庫當事實來源。這不是架構的妥協,而是各就各位。

小結

「向量資料庫 vs MongoDB」其實是個假對立——它們一個管「像不像」、一個管「是不是」,在 RAG 系統裡是上下游的合作關係。真正要做的決定是:你的語意檢索需求,重到值得為它養一個專用引擎嗎? 我的答案是值得——混合檢索與檢索層權限過濾這兩件事,就足以讓 Qdrant 在架構裡站穩位置。

系列下一篇的主題還在構思,可能是混合檢索與 Rerank 的深入拆解,或是檢索層權限設計的完整實作。敬請期待。

Creative Commons 姓名標示 非商業性

本文採用 CC BY-NC 4.0 授權

歡迎轉載與引用,請標明出處(向量資料庫與 MongoDB 差在哪?從一個同時用 Qdrant 和 MongoDB 的專案說起 — EmptyWu);禁止用於商業用途。

商業使用或合作提案,歡迎來信洽談:[email protected]

留言
分享

留言