LESSON 30分

ストーリー

田中VPoE
ハイブリッド検索に加えて、メタデータフィルタリングも検索精度の向上に大きく貢献する
あなた
Step 2で設計したメタデータを検索時に使うんですね
田中VPoE
そうだ。「開発部の技術文書の中から」「2025年以降の議事録から」といった条件で検索対象を絞り込む。これにより、無関係なドキュメントがヒットするのを防げる
あなた
フィルタリングはベクトル検索の前にやるべきですか?後にやるべきですか?
田中VPoE
いい質問だ。プリフィルタとポストフィルタ、それぞれにメリットとデメリットがある。ユースケースに応じて使い分けよう

プリフィルタ vs ポストフィルタ

比較

観点プリフィルタポストフィルタ
実行タイミングベクトル検索の前ベクトル検索の後
仕組みフィルタ条件に合うドキュメントのみを検索対象にする全ドキュメントを検索後、条件に合わない結果を除外
メリット検索対象が絞られるため高速、結果が安定ベクトル検索の精度に影響なし
デメリットフィルタ後のデータが少ないとTop-K不足になる除外後に結果が少なくなる可能性、無駄な検索コスト
適するケースフィルタ条件が明確で、対象データが十分にある場合フィルタ条件が曖昧、またはフィルタ後のデータ量が不明な場合
プリフィルタの流れ:

[フィルタ条件] doc_type = "技術文書" AND department = "開発部"

[ベクトルDB] フィルタ条件に合うベクトルのみを対象に類似度検索

[結果] Top-K(すべてフィルタ条件を満たす)

ポストフィルタの流れ:

[ベクトルDB] 全ベクトルを対象に類似度検索 → Top-K取得

[フィルタ適用] doc_type = "技術文書" AND department = "開発部"

[結果] フィルタ後の結果(K件より少ない可能性あり)

フィルタ演算子

Qdrantで利用可能なフィルタ

演算子説明
match (keyword)完全一致doc_type = "技術文書"
match (text)テキスト検索content contains "RAG"
range範囲指定updated_at >= "2025-01-01"
geo地理的範囲(位置情報がある場合)
values_count配列要素数tags の数 >= 2
is_nullNULL判定project is not null
has_idID指定特定のIDリストに含まれるか

複合フィルタの構築

複合フィルタの例:

Must(AND条件):
  - doc_type = "技術文書"
  - updated_at >= "2025-01-01"

Should(OR条件):
  - department = "開発部"
  - department = "インフラ部"

Must Not(NOT条件):
  - tags contains "deprecated"

→ 結果: 2025年以降に更新された、開発部またはインフラ部の技術文書で、
         deprecatedタグが付いていないもの

ファセット検索

ファセット検索は、検索結果をメタデータのカテゴリ別に集計する手法です。

ファセット検索のUI例:

検索: "RAGの構築方法"

[検索結果] 45件

[ファセット(絞り込みパネル)]
├── ドキュメント種別
│   ├── 技術文書 (28件)
│   ├── 議事録 (12件)
│   └── FAQ (5件)
├── 部門
│   ├── 開発部 (30件)
│   ├── インフラ部 (10件)
│   └── データチーム (5件)
├── 更新時期
│   ├── 直近1ヶ月 (15件)
│   ├── 直近3ヶ月 (25件)
│   └── それ以前 (5件)
└── 技術スタック
    ├── Python (20件)
    ├── LangChain (15件)
    └── Qdrant (10件)

ファセット実装のポイント

ポイント説明
集計対象のフィールドカーディナリティが低い(値の種類が少ない)フィールドが適切
表示順件数の多い順が一般的
動的更新フィルタを適用するとファセットの件数も再計算される
パフォーマンスベクトルDB側での集計がサポートされていない場合、アプリケーション側で実装

自動フィルタ生成

ユーザーの自然言語クエリからメタデータフィルタを自動生成する手法です。

自動フィルタ生成の流れ:

ユーザーの質問: "開発部が先月作った技術文書でRAGに関するもの"

→ LLMでフィルタ条件を抽出:
{
  "department": "開発部",
  "doc_type": "技術文書",
  "updated_at": { "gte": "2026-02-01", "lte": "2026-02-28" },
  "search_query": "RAG"
}

→ フィルタ条件をベクトルDBのクエリに変換
→ メタデータフィルタ + ベクトル検索を実行

自動フィルタ生成の設計

要素実装方法
フィルタ候補の定義利用可能なフィルタフィールドと値の候補をLLMに提示
LLMプロンプト構造化出力(JSON)でフィルタ条件を返すように指示
バリデーションLLM出力のフィルタ条件をスキーマで検証
フォールバックフィルタ生成に失敗した場合はフィルタなしで検索

「自動フィルタ生成は便利だが、LLMの出力が常に正確とは限らない。バリデーションとフォールバックは必須だ」 — 田中VPoE


NetShop社のフィルタリング設計

フィルタタイプ用途
doc_typeプリフィルタドキュメント種別の絞り込み
departmentプリフィルタ部門ごとの検索
updated_atプリフィルタ鮮度による絞り込み
tagsプリフィルタタグベースの絞り込み
tech_stackプリフィルタ技術領域での絞り込み
has_codeポストフィルタコードを含むドキュメントの優先

まとめ

ポイント内容
プリフィルタ検索前に絞り込み。高速で安定した結果
ポストフィルタ検索後に絞り込み。ベクトル検索精度に影響なし
ファセット検索カテゴリ別の集計でユーザーの絞り込みをサポート
自動フィルタLLMで自然言語からフィルタ条件を自動抽出

チェックリスト

  • プリフィルタとポストフィルタの違いと使い分けを理解した
  • 複合フィルタの構築方法を理解した
  • ファセット検索の設計ポイントを理解した
  • 自動フィルタ生成の仕組みと注意点を理解した

次のステップへ

次は「検索パイプライン構築」を学びます。Retriever、Reranker、Generatorを統合した検索パイプラインの設計に取り組みましょう。


推定読了時間: 30分