「都是資料庫,為什麼 RAG 要特地用向量資料庫?MongoDB 不行嗎?」——這是我被問過、也曾自問過的問題。最好的回答方式不是抽象比較,而是看一個真實的架構:我的企業文件問答平台(上一篇介紹過)同時用了 Qdrant 和 MongoDB,兩者各司其職、誰也取代不了誰。這篇從「它們根本在回答不同的問題」講起,最後整理成何時該用哪個的判斷準則。
一、核心差異:兩種完全不同的「查詢」
先把最本質的差異放在最前面。
MongoDB 回答的問題是:「找出符合條件的資料。」
1 | // 找出「業務部」所有「已完成」的任務 |
這是精確匹配的世界:條件成立就回傳,不成立就不回傳,結果非黑即白。底層靠 B-tree 索引,本質上是排好序的目錄,查詢是「翻到那一頁」。
向量資料庫回答的問題是:「找出跟這個東西最『像』的資料。」
1 | # 找出跟「員工請假要跑什麼流程」語意最接近的 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 的深入拆解,或是檢索層權限設計的完整實作。敬請期待。
留言