{"title":"FTS5 フルテキスト検索","slug":"fts5-search","category":"concepts","summary":"Synapse が SQLite FTS5 を使用してサブミリ秒のフルテキストメモリ検索を実現する仕組み。","audience":["human","llm"],"tags":["concept","search","fts5","fulltext"],"difficulty":"advanced","updated":"2026-06-27","word_count":269,"read_minutes":1,"lang":"ja","translated":true,"requested_lang":"ja","content_markdown":"\n# FTS5 フルテキスト検索\n\nSynapse は高速かつ柔軟なメモリ検索のために FTS5（Full-Text Search 5）を使用しています。本ページでは、その仕組みと効果的な使い方を説明します。\n\n## FTS5 とは？\n\nFTS5 はフルテキスト検索機能を提供する SQLite 拡張（PostgreSQL でも拡張経由で利用可能）です。以下をサポートします。\n\n- テキストコンテンツのインデックスによる高速キーワード検索\n- ブール演算子（AND、OR、NOT）\n- 引用符によるフレーズマッチング\n- `*` によるプレフィックスマッチング\n- 関連度による結果ランキング\n\nSynapse は全メモリコンテンツを FTS5 でインデックス化し、数千件のメモリにわたるサブミリ秒検索を可能にしています。\n\n## Synapse での FTS5 利用\n\n`POST /memory` 時の処理：\n\n1. メモリコンテンツが `memories` テーブルに保存\n2. コンテンツが FTS5 仮想テーブルにも挿入\n3. FTS5 が自動的にトークン化とインデックス化を実行\n\n`GET /memory/search?q=...` 時の処理：\n\n1. Synapse が FTS5 構文でクエリを解析\n2. FTS5 インデックスに対して `MATCH` を実行\n3. `mind_id` でフィルタ（テナント分離）\n4. ランク付けされた結果を返却\n\n## クエリ構文\n\n### 単純なキーワード検索\n\n```\n?q=docker\n```\n\n「docker」を含むメモリを返します。\n\n### 複数キーワード（暗黙の AND）\n\n```\n?q=docker+swarm\n?q=docker%20swarm\n```\n\n「docker」と「swarm」の両方を含むメモリを返します。\n\n### フレーズマッチング\n\n```\n?q=\"docker+swarm\"\n?q=%22docker%20swarm%22\n```\n\n完全なフレーズ「docker swarm」を含むメモリを返します。\n\n### プレフィックスマッチング\n\n```\n?q=docker*\n```\n\n「docker」で始まる単語（「dockers」「dockerfile」「dockerize」など）を含むメモリを返します。\n\n### ブール OR\n\n```\n?q=docker+OR+kubernetes\n```\n\n「docker」または「kubernetes」を含むメモリを返します。\n\n### ブール NOT\n\n```\n?q=docker+-swarm\n?q=docker+NOT+swarm\n```\n\n「docker」を含むが「swarm」を含まないメモリを返します。\n\n### グループ化\n\n```\n?q=(docker+OR+kubernetes)+-test\n```\n\n「docker」または「kubernetes」を含むが「test」を含まないメモリを返します。\n\n## 実践例\n\n### プロジェクトに関するメモリの検索\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=synapse+deployment\"\n```\n\n### 完全フレーズの検索\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=%22docker+swarm%22\"\n```\n\n### テストメモリの除外\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=production+-test\"\n```\n\n### 技術による検索\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=(postgres+OR+sqlite)+-mysql\"\n```\n\n## ランキング\n\nFTS5 は BM25 アルゴリズムで関連度により結果をランク付けします。考慮要素：\n\n- 用語頻度（用語の出現回数）\n- 逆文書頻度（まれな用語ほど上位）\n- 文書長（短い文書ほど上位）\n- カラムウェイト（title > content）\n\n結果はランク順（最も関連度の高いものが先頭）で返されます。\n\n## パフォーマンス\n\n| 操作 | レイテンシ |\n|-----------|---------|\n| 100 件のメモリ検索 | < 5ms |\n| 1,000 件のメモリ検索 | < 10ms |\n| 10,000 件のメモリ検索 | < 25ms |\n| 100,000 件のメモリ検索 | < 100ms |\n\nFTS5 は読み取り中心のワークロードに高度に最適化されています。\n\n## 制限事項\n\n### ステミング\n\nFTS5 はデフォルトでステミングを行いません。「running」と「run」は異なる用語として扱われます。\n\n**回避策：** プレフィックスマッチングを使用 — `?q=run*`\n\n### 誤字許容\n\nFTS5 はファジーマッチングをサポートしません。誤字があると結果が返りません。\n\n**回避策：** 概念マッチングにはセマンティック検索（`/memory/semantic-search`）を使用してください。\n\n### ストップワード\n\n一般的な単語（the、a、an、is）はインデックス化されますが、検索には有用でない場合があります。FTS5 はこれを自動的に処理します。\n\n## FTS5 とセマンティック検索の比較\n\n| 側面 | FTS5 | セマンティック検索 |\n|--------|------|-----------------|\n| 速度 | サブミリ秒 | 50〜100ms |\n| マッチング | 完全キーワード | 概念的 |\n| 誤字許容 | なし | 一部あり |\n| ステミング | なし | 暗黙的 |\n| 埋め込み必要 | 不要 | 必要 |\n| 最適な用途 | 特定の用語 | 概念 |\n\nキーワードが分かっている場合は FTS5 を使用してください。X が異なる表現で記述されている「X に関するメモリ」を探す場合はセマンティック検索を使用してください。\n\n## ベストプラクティス\n\n> [!TIP]\n> - **具体的な用語を使用** — 「container orchestration」より「docker swarm」が良い\n> - **フレーズを引用** — `\"docker swarm\"` でフレーズマッチを確実に\n> - **バリエーションにプレフィックス** — `deploy*` で「deploy」「deployment」「deploying」を捕捉\n> - **ノイズを除外** — `-test` でテストメモリをフィルタ\n> - **タグと組み合わせ** — `?q=docker&tag=production` で結果を絞り込み\n\n## 次のステップ\n\n- [Semantic Search](/docs/concepts/semantic-search)\n- [Memory API](/docs/api/memory)\n- [Memory Best Practices](/docs/guides/memory-best-practices)\n","content_html":"<h1>FTS5 フルテキスト検索</h1>\n<p>Synapse は高速かつ柔軟なメモリ検索のために FTS5（Full-Text Search 5）を使用しています。本ページでは、その仕組みと効果的な使い方を説明します。</p>\n<h2>FTS5 とは？</h2>\n<p>FTS5 はフルテキスト検索機能を提供する SQLite 拡張（PostgreSQL でも拡張経由で利用可能）です。以下をサポートします。</p>\n<ul>\n<li>テキストコンテンツのインデックスによる高速キーワード検索</li>\n<li>ブール演算子（AND、OR、NOT）</li>\n<li>引用符によるフレーズマッチング</li>\n<li><code>*</code> によるプレフィックスマッチング</li>\n<li>関連度による結果ランキング</li>\n</ul>\n<p>Synapse は全メモリコンテンツを FTS5 でインデックス化し、数千件のメモリにわたるサブミリ秒検索を可能にしています。</p>\n<h2>Synapse での FTS5 利用</h2>\n<p><code>POST /memory</code> 時の処理：</p>\n<ol>\n<li>メモリコンテンツが <code>memories</code> テーブルに保存</li>\n<li>コンテンツが FTS5 仮想テーブルにも挿入</li>\n<li>FTS5 が自動的にトークン化とインデックス化を実行</li>\n</ol>\n<p><code>GET /memory/search?q=...</code> 時の処理：</p>\n<ol>\n<li>Synapse が FTS5 構文でクエリを解析</li>\n<li>FTS5 インデックスに対して <code>MATCH</code> を実行</li>\n<li><code>mind_id</code> でフィルタ（テナント分離）</li>\n<li>ランク付けされた結果を返却</li>\n</ol>\n<h2>クエリ構文</h2>\n<h3>単純なキーワード検索</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker</code></pre><p>「docker」を含むメモリを返します。</p>\n<h3>複数キーワード（暗黙の AND）</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker+swarm\n?q=docker%20swarm</code></pre><p>「docker」と「swarm」の両方を含むメモリを返します。</p>\n<h3>フレーズマッチング</h3>\n<pre><code class=\"hljs language-plaintext\">?q=&quot;docker+swarm&quot;\n?q=%22docker%20swarm%22</code></pre><p>完全なフレーズ「docker swarm」を含むメモリを返します。</p>\n<h3>プレフィックスマッチング</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker*</code></pre><p>「docker」で始まる単語（「dockers」「dockerfile」「dockerize」など）を含むメモリを返します。</p>\n<h3>ブール OR</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker+OR+kubernetes</code></pre><p>「docker」または「kubernetes」を含むメモリを返します。</p>\n<h3>ブール NOT</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker+-swarm\n?q=docker+NOT+swarm</code></pre><p>「docker」を含むが「swarm」を含まないメモリを返します。</p>\n<h3>グループ化</h3>\n<pre><code class=\"hljs language-plaintext\">?q=(docker+OR+kubernetes)+-test</code></pre><p>「docker」または「kubernetes」を含むが「test」を含まないメモリを返します。</p>\n<h2>実践例</h2>\n<h3>プロジェクトに関するメモリの検索</h3>\n<pre><code class=\"hljs language-bash\">curl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n     <span class=\"hljs-string\">&quot;https://synapse.schaefer.zone/memory/search?q=synapse+deployment&quot;</span></code></pre><h3>完全フレーズの検索</h3>\n<pre><code class=\"hljs language-bash\">curl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n     <span class=\"hljs-string\">&quot;https://synapse.schaefer.zone/memory/search?q=%22docker+swarm%22&quot;</span></code></pre><h3>テストメモリの除外</h3>\n<pre><code class=\"hljs language-bash\">curl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n     <span class=\"hljs-string\">&quot;https://synapse.schaefer.zone/memory/search?q=production+-test&quot;</span></code></pre><h3>技術による検索</h3>\n<pre><code class=\"hljs language-bash\">curl -H <span class=\"hljs-string\">&quot;Authorization: Bearer YOUR_MIND_KEY&quot;</span> \\\n     <span class=\"hljs-string\">&quot;https://synapse.schaefer.zone/memory/search?q=(postgres+OR+sqlite)+-mysql&quot;</span></code></pre><h2>ランキング</h2>\n<p>FTS5 は BM25 アルゴリズムで関連度により結果をランク付けします。考慮要素：</p>\n<ul>\n<li>用語頻度（用語の出現回数）</li>\n<li>逆文書頻度（まれな用語ほど上位）</li>\n<li>文書長（短い文書ほど上位）</li>\n<li>カラムウェイト（title &gt; content）</li>\n</ul>\n<p>結果はランク順（最も関連度の高いものが先頭）で返されます。</p>\n<h2>パフォーマンス</h2>\n<table>\n<thead>\n<tr>\n<th>操作</th>\n<th>レイテンシ</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>100 件のメモリ検索</td>\n<td>&lt; 5ms</td>\n</tr>\n<tr>\n<td>1,000 件のメモリ検索</td>\n<td>&lt; 10ms</td>\n</tr>\n<tr>\n<td>10,000 件のメモリ検索</td>\n<td>&lt; 25ms</td>\n</tr>\n<tr>\n<td>100,000 件のメモリ検索</td>\n<td>&lt; 100ms</td>\n</tr>\n</tbody></table>\n<p>FTS5 は読み取り中心のワークロードに高度に最適化されています。</p>\n<h2>制限事項</h2>\n<h3>ステミング</h3>\n<p>FTS5 はデフォルトでステミングを行いません。「running」と「run」は異なる用語として扱われます。</p>\n<p><strong>回避策：</strong> プレフィックスマッチングを使用 — <code>?q=run*</code></p>\n<h3>誤字許容</h3>\n<p>FTS5 はファジーマッチングをサポートしません。誤字があると結果が返りません。</p>\n<p><strong>回避策：</strong> 概念マッチングにはセマンティック検索（<code>/memory/semantic-search</code>）を使用してください。</p>\n<h3>ストップワード</h3>\n<p>一般的な単語（the、a、an、is）はインデックス化されますが、検索には有用でない場合があります。FTS5 はこれを自動的に処理します。</p>\n<h2>FTS5 とセマンティック検索の比較</h2>\n<table>\n<thead>\n<tr>\n<th>側面</th>\n<th>FTS5</th>\n<th>セマンティック検索</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>速度</td>\n<td>サブミリ秒</td>\n<td>50〜100ms</td>\n</tr>\n<tr>\n<td>マッチング</td>\n<td>完全キーワード</td>\n<td>概念的</td>\n</tr>\n<tr>\n<td>誤字許容</td>\n<td>なし</td>\n<td>一部あり</td>\n</tr>\n<tr>\n<td>ステミング</td>\n<td>なし</td>\n<td>暗黙的</td>\n</tr>\n<tr>\n<td>埋め込み必要</td>\n<td>不要</td>\n<td>必要</td>\n</tr>\n<tr>\n<td>最適な用途</td>\n<td>特定の用語</td>\n<td>概念</td>\n</tr>\n</tbody></table>\n<p>キーワードが分かっている場合は FTS5 を使用してください。X が異なる表現で記述されている「X に関するメモリ」を探す場合はセマンティック検索を使用してください。</p>\n<h2>ベストプラクティス</h2>\n<div class=\"callout callout-ok\"></div><h2>次のステップ</h2>\n<ul>\n<li><a href=\"/docs/concepts/semantic-search\">Semantic Search</a></li>\n<li><a href=\"/docs/api/memory\">Memory API</a></li>\n<li><a href=\"/docs/guides/memory-best-practices\">Memory Best Practices</a></li>\n</ul>\n","urls":{"html":"/docs/concepts/fts5-search","text":"/docs/concepts/fts5-search?format=text","json":"/docs/concepts/fts5-search?format=json","llm":"/docs/concepts/fts5-search?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}