Qdrant 讓 RAG 先過濾再找相似
我拆 Raunaq 的向量資料庫比較,整理出 filter-first RAG 的選型邏輯與可直接貼上的設計模板。

我把 Raunaq 的向量資料庫比較拆成一套 filter-first RAG 做法,直接給你可抄的設計模板。
我做 RAG 做到後面,最煩的不是 embedding 不準,而是系統明明看起來都對,實際一加條件就開始鬧脾氣。你要 tenant、要時間區間、要來源限定,結果檢索不是少給,就是給錯,還常常是那種「數學上沒錯、產品上很爛」的輸出。我以前也以為這只是 top-k 調一調的事,後來才發現不是。問題根本在架構:你到底是先找相似,再補過濾,還是先把範圍縮對,再找相似。
這次我看的來源是 Raunaq 的 Vector Databases for RAG,他把 pgvector、ChromaDB、Qdrant 放在同一個問題底下看:當你的向量查詢一定要尊重 metadata 時,誰是真的能打,誰只是 demo 好看。他沒有講虛的,這點我很買單。
真正難的不是相似度,是子集合相似度
訂閱 AI 趨勢週報
每週精選模型發布、工具應用與深度分析,直送信箱。不定期,不騷擾。
不會寄垃圾信,隨時可取消。
“A real-world vector search isn’t just ‘find similar vectors’ — it’s ‘find similar vectors within a subset.’”
翻譯一下就是:你在 production 裡做的,從來不是純向量搜尋,而是「在某個限制範圍內找最像的內容」。我如果做客服助理,不會想要整家公司最像的工單,我要的是這個 tenant、這個專案、這段時間、這種文件類型裡最像的那幾段。範圍才是主角,相似度只是第二步。

Raunaq 這個切法很重要,因為它把很多 RAG 的假問題直接拆穿。很多團隊在 notebook 裡看起來都很順,一上線就開始怪 embedding、怪 chunking、怪模型。其實不是。真正的問題是你把「語意排序」跟「權限/範圍控制」混在一起了。向量索引懂語意,metadata 懂條件,這兩個東西本來就不是天生會合作的。
我之前做過一個多租戶知識庫,早期偷懶,直接一張向量表加一個 tenant_id 欄位就上了。小流量時還行,等到某個 tenant 的文件量暴增,檢索品質就開始飄。明明應該回 10 段,結果有時候只回 3 段,有時候回 10 段但一半沒用。最煩的是 log 看起來完全正常,因為資料庫真的只是照你的規則在跑。
實操寫法很簡單:在選向量庫之前,先把「子集合規則」寫清楚。不是先決定 embedding model,也不是先挑 chunk size,而是先回答這幾件事:
- 你有哪些必須套用的 filter?
- 這些 filter 的選擇性高不高?
- 這些條件會不會常變?
如果你答不出來,就先別急著選產品。你是在盲選儲存架構,不是在做技術決策。
先查再過濾,最容易把 recall 偷偷弄爛
pgvector 這條路我很熟,也不是不能用。它的優點很直白:你本來就跑 Postgres,資料、權限、交易、運維都在同一套裡,簡單到讓人舒服。問題是很多人把它拿去做有嚴格 filter 的 RAG,然後還期待結果穩定,這就有點想太多了。
Raunaq 講的 post-filtering 很關鍵:先做向量 top-k,再把 metadata filter 套上去。聽起來很省事,因為你吃到了向量索引的速度;但只要 filter 夠窄,這招就開始漏。你要 10 筆,結果 top-k 裡 8 筆被 filter 掉,最後只剩 2 筆。系統不會跳警告,它只會很安靜地交出一份不完整答案。
也就是說,post-filtering 最大的坑不是慢,而是「看起來正常」。你會以為是 embedding 不夠好、chunk 切太大、模型太爛,然後開始亂調參數。其實根本不是模型問題,是你的候選池沒有為 filter 留空間。這種錯很貴,因為你會在錯的地方花很多時間。
我之前看過一個內部搜尋專案,團隊一直嫌召回差,最後才發現是 tenant filter 太窄,卻還用一般 top-k 當標準。這種情況下,調再多 embedding 都沒用。你是在用錯的檢索策略硬撐。
實操寫法:
- 如果你一定要 post-filter,就先 oversample,再看過濾後還剩多少。
- 不要只看 top-k,要看「requested k vs returned k」。
- 拿最窄的 tenant、最小的來源集、最嚴的日期區間來測。
如果最差情境都穩,才輪得到你談模型品質。
先過濾再找,才是真的尊重條件
ChromaDB 走的是另一條路:先過濾,再在過濾後的集合裡找相似。Raunaq 的描述很清楚,metadata 先走 SQLite,拿到符合條件的 ID,再在這個範圍內做向量搜尋。這不是什麼花俏做法,但它有一個很重要的優點:結果是誠實的。

翻譯一下就是,如果你的 filter 只命中一小塊資料,系統就只在那一小塊裡找,不會先拿一堆看起來很像、其實不合格的候選來湊數。對 local 開發、原型驗證、小型知識庫來說,這種 predictable 行為其實很舒服。我自己也用過這種設計,因為我當時要的是「先能工作」,不是「先把 infra 搞到很漂亮」。
但它的代價也很直接:如果過濾後的集合很大, brute force 會開始痛。你一旦不是在小集合裡找,速度就不會太好看。說白了,Chroma 的強項是簡單和正確,不是大規模 selective query 的效率。
Raunaq 也提到 embedded mode 的運作方式很方便,但在某些 crash 窗口裡,metadata 跟向量索引的狀態可能會讓你不太安心。這種事平常不會發生在 demo,通常都發生在你最不想重跑資料的時候。很煩,但這就是實務。
實操寫法:
- 當你要的是 local dev、概念驗證、或小資料集,先用 filter-first 很合理。
- 當你的 filtered subset 會長到很大,就不要硬撐 brute force。
- 如果你很在意查詢結果一定要符合條件,先過濾通常比先向量化更踏實。
Qdrant 之所以順,是因為它從一開始就把 filter 當主角
我看 Raunaq 那篇最有感的地方,是他把 Qdrant 講得很像一個真的有在想 production 的系統。它不是把 metadata 當附屬品,而是把 payload index 跟 vector index 一起設計。這件事聽起來很小,實際上差很多。
也就是說,Qdrant 不是先假設「先找相似再說」,而是直接承認 query 本來就是混合型的:你既要語意相似,也要條件符合。它會先用 payload index 找出符合條件的 ID,再讓向量檢索只在這些 ID 裡面跑。這個方向我很認同,因為它不是在補洞,是在一開始就把洞補好。
我特別在意 Raunaq 提到的 filter bitmap。這種東西看起來像底層細節,實際上就是檢索正不正確的分水嶺。當 filter 很窄時,系統能不能先把可用候選縮出來,決定了你會不會拿到一堆不該出現的 chunk。這不是「優化」,這是基本功。
Qdrant 還有一個我很吃的點:它不是只給你一種儲存姿勢。in-memory、memory-mapped、on-disk 都有,這表示你可以依資料量跟機器條件調整,不必每次都把 RAM 當信仰。我個人會先偏向 mmap,讓 OS 幫你做快取,少一點自己手動照顧記憶體的痛苦。
實操寫法:如果你的產品有多租戶、ACL、每人不同可見範圍、或很明確的 metadata 條件,從一開始就把 filter-aware engine 放進候選。不要等到系統長歪了才補。重構 retrieval schema 比你想像中更煩,尤其是已經有使用者在上面跑的時候。
分段儲存讓 Qdrant 比較不像紙糊的
Raunaq 的圖我也很喜歡,因為它把 Qdrant 的 segmented storage 講得很清楚。這不是什麼簡報上好看的架構圖而已,它直接影響你在大量寫入下,系統會不會開始抖。
翻譯一下就是:新資料會先進到可追加的 segment,背景再慢慢做優化、合併、重建,不需要整個 collection 停機重來。這跟那種「先停機再重建索引」的做法差很多。我真的很不喜歡後者,因為它把日常營運變成維護排程,然後大家還得假裝這很正常。
分段儲存的價值不只是在寫入快,而是它讓系統可以邊長大邊維持可用。對 RAG 來說,資料不是固定不動的。文件會一直進來、刪掉、更新、重排。如果你的檢索層在這種情況下容易失真,那你再會調 embedding 也沒用。
我之前碰過一個文件平台,白天一直 ingest,晚上還要被搜尋。結果一到重建索引時間,整個 retrieval 就像踩到香蕉皮。後來我才真正理解,RAG 的問題不是只看 query latency,而是看它在「持續變動」下還能不能維持正常。
實操寫法:
- 問清楚資料庫怎麼處理 writes、compaction、index rebuild。
- 如果答案聽起來像要排維護窗口,先小心。
- 把「10M inserts、delete、tenant churn、bad deploy」都拿來想一遍。
你會發現,很多系統不是不能用,是一碰到真實營運就開始露餡。
選型不要看品牌,要看你的 filter 痛點
Raunaq 這篇最有用的地方,不是幫你選出唯一答案,而是逼你承認:不同資料庫對 filter 的態度真的不一樣。你如果把這件事看成「哪個向量庫比較紅」,那你大概會選錯。
我自己的簡化版判斷是這樣:
- pgvector:你本來就重度依賴 Postgres,filter 很鬆,想把運維壓力壓到最低。
- ChromaDB:你在做 local dev、原型、或小型資料集,想先把流程跑通。
- Qdrant:你的檢索本身就高度依賴 filter,多租戶、權限、條件查詢是日常,不是邊角料。
我不是在說 pgvector 不行。相反,我覺得它在很多場景都很合理,尤其是你本來就活在 Postgres 世界裡的時候。但如果你的產品核心就是「在一堆條件裡找對內容」,那你就不要再拿一個只是在資料庫外面順手補向量能力的方案硬撐。那通常會變成後面幾個月的技術債。
實操寫法:先寫你的 95th percentile query。不要寫抽象需求,直接寫真實 query:
- 這個 tenant 有多少文件?
- 這個 filter 平均命中多少比例?
- 最窄的條件會縮到多小?
如果你連這些都沒算過,就先不要選庫。你不是在選工具,你是在賭未來會不會被自己打臉。
可抄的模板
# Filter-first RAG 設計模板(可直接貼到 design doc)
## 1. 先定義子集合,不要先談 embedding
- tenant_id:必填 / 選填
- source:必填 / 選填
- date_range:必填 / 選填
- acl_rule:必填 / 選填
- selectivity:
- broad:> 50% corpus
- medium:5%–50%
- narrow:< 5%
## 2. 依 filter 選檢索策略
- broad filter:post-filtering 可接受
- medium filter:先 oversample,再驗證 recall
- narrow filter:優先 filter-first / filter-aware retrieval
## 3. 每個 chunk 都要帶 metadata
{
"id": "chunk_123",
"tenant_id": "tenant_a",
"source": "docs",
"doc_id": "doc_456",
"created_at": "2026-06-02T00:00:00Z",
"tags": ["billing", "policy"],
"embedding": [/* vector */],
"text": "chunk text here"
}
## 4. 檢索合約
Input:
- query_text
- filters
- top_k
Output:
- results 必須符合 filters
- 系統可內部 oversample
- 若不足 top_k,允許回傳較少結果,但要明確標示
## 5. 資料庫選型規則
- pgvector:已經在用 Postgres、filter 較鬆、想少一套運維
- ChromaDB:local prototyping、小資料集、要快點跑起來
- Qdrant:selective filters、多租戶、ACL、production retrieval
## 6. 必測案例
- no filter
- single tenant filter
- highly selective tenant filter
- date range filter
- tenant + source filter
- worst-case tenant with smallest corpus
## 7. 要記錄的 metrics
- requested_top_k
- returned_count
- filter_selectivity
- latency_ms
- recall_on_test_set
- fallback_used
## 8. Prompt / 生成規則
Only pass chunks that satisfy the filter.
If fewer chunks are available, do not invent missing context.
## 9. 決策備註範例
- "We chose Qdrant because our retrieval is tenant-scoped and filters are often selective."
- "We chose pgvector because our data already lives in Postgres and filters are broad."
- "We chose ChromaDB for local prototyping and offline document search."這段我會直接貼進自己的設計文件裡,因為它逼團隊先把檢索條件講清楚,再來談工具。這樣至少不會一開始就把問題做歪。
原始來源是 https://raunaqness.substack.com/p/vector-databases-for-rag。我上面對 pgvector、ChromaDB、Qdrant 的整理是衍生解讀;模板與實作寫法是我根據同一個 filter-first 觀念重寫成可直接拿去開 design review 的版本。