{"title":"FTS5 Full-Text Search","slug":"fts5-search","category":"concepts","summary":"วิธีที่ Synapse ใช้ SQLite FTS5 สำหรับการค้นหา memory แบบ full-text ในระดับ sub-millisecond","audience":["human","llm"],"tags":["concept","search","fts5","fulltext"],"difficulty":"advanced","updated":"2026-06-27","word_count":434,"read_minutes":2,"lang":"th","translated":true,"requested_lang":"th","content_markdown":"\n# FTS5 Full-Text Search\n\nSynapse ใช้ FTS5 (Full-Text Search 5) สำหรับการค้นหา memory ที่รวดเร็วและยืดหยุ่น เอกสารหน้านี้อธิบายวิธีการทำงานและวิธีใช้อย่างมีประสิทธิภาพ\n\n## FTS5 คืออะไร?\n\nFTS5 เป็น SQLite extension (มีใน PostgreSQL ผ่าน extension ด้วย) ที่ให้ความสามารถ full-text search โดย:\n\n- Index เนื้อหา text สำหรับ keyword search ที่รวดเร็ว\n- รองรับ boolean operator (AND, OR, NOT)\n- รองรับ phrase matching ด้วยเครื่องหมายคำพูด\n- รองรับ prefix matching ด้วย `*`\n- จัดอันดับผลลัพธ์ตามความเกี่ยวข้อง\n\nSynapse ใช้ FTS5 ในการ index เนื้อหา memory ทั้งหมด เปิดใช้งานการค้นหาในระดับ sub-millisecond ทั่ว memory หลายพันรายการ\n\n## วิธีที่ Synapse ใช้ FTS5\n\nเมื่อคุณ `POST /memory`:\n\n1. เนื้อหา memory ถูกเก็บในตาราง `memories`\n2. เนื้อหายังถูกแทรกลงใน FTS5 virtual table\n3. FTS5 แบ่งคำและ index เนื้อหาโดยอัตโนมัติ\n\nเมื่อคุณ `GET /memory/search?q=...`:\n\n1. Synapse แยกวิเคราะห์ query โดยใช้ไวยากรณ์ FTS5\n2. ปฏิบัติการ `MATCH` กับ FTS5 index\n3. กรองตาม `mind_id` (tenant isolation)\n4. ส่งกลับผลลัพธ์ที่จัดอันดับแล้ว\n\n## ไวยากรณ์ Query\n\n### ค้นหา keyword แบบง่าย\n\n```\n?q=docker\n```\n\nส่งกลับ memory ที่มี \"docker\"\n\n### หลาย keyword (AND โดยนัย)\n\n```\n?q=docker+swarm\n?q=docker%20swarm\n```\n\nส่งกลับ memory ที่มีทั้ง \"docker\" และ \"swarm\"\n\n### Phrase matching\n\n```\n?q=\"docker+swarm\"\n?q=%22docker%20swarm%22\n```\n\nส่งกลับ memory ที่มี phrase \"docker swarm\" ตรงตัว\n\n### Prefix matching\n\n```\n?q=docker*\n```\n\nส่งกลับ memory ที่มีคำขึ้นต้นด้วย \"docker\" (เช่น \"dockers\", \"dockerfile\", \"dockerize\")\n\n### Boolean OR\n\n```\n?q=docker+OR+kubernetes\n```\n\nส่งกลับ memory ที่มี \"docker\" หรือ \"kubernetes\"\n\n### Boolean NOT\n\n```\n?q=docker+-swarm\n?q=docker+NOT+swarm\n```\n\nส่งกลับ memory ที่มี \"docker\" แต่ไม่มี \"swarm\"\n\n### การจัดกลุ่ม\n\n```\n?q=(docker+OR+kubernetes)+-test\n```\n\nส่งกลับ memory ที่มี \"docker\" หรือ \"kubernetes\" แต่ไม่มี \"test\"\n\n## ตัวอย่างปฏิบัติ\n\n### ค้นหา memory เกี่ยวกับโปรเจกต์\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=synapse+deployment\"\n```\n\n### ค้นหา phrase ตรงตัว\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_MIND_KEY\" \\\n     \"https://synapse.schaefer.zone/memory/search?q=%22docker+swarm%22\"\n```\n\n### แยก memory ทดสอบออก\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- ความถี่ของคำ (term ปรากฏบ่อยแค่ไหน)\n- Inverse document frequency (คำที่หายากอันดับสูงกว่า)\n- ความยาวเอกสาร (เอกสารสั้นที่มีคำนั้นอันดับสูงกว่า)\n- น้ำหนัก column (title > content)\n\nผลลัพธ์ส่งกลับตามลำดับอันดับ (เกี่ยวข้องที่สุดก่อน)\n\n## ประสิทธิภาพ\n\n| การดำเนินการ | Latency |\n|-----------|---------|\n| ค้นหา 100 memory | < 5ms |\n| ค้นหา 1,000 memory | < 10ms |\n| ค้นหา 10,000 memory | < 25ms |\n| ค้นหา 100,000 memory | < 100ms |\n\nFTS5 ถูกปรับให้เหมาะกับ workload ที่อ่านหนัก\n\n## ข้อจำกัด\n\n### Stemming\n\nFTS5 ไม่ทำ stemming โดยค่าเริ่มต้น \"running\" และ \"run\" เป็นคำต่างกัน\n\n**วิธีแก้:** ใช้ prefix matching: `?q=run*`\n\n### ความทนต่อการพิมพ์ผิด\n\nFTS5 ไม่รองรับ fuzzy matching พิมพ์ผิดจะไม่ส่งกลับผลลัพธ์\n\n**วิธีแก้:** ใช้ semantic search (`/memory/semantic-search`) สำหรับการจับคู่เชิงแนวคิด\n\n### Stop word\n\nคำทั่วไป (the, a, an, is) ถูก index แต่อาจไม่มีประโยชน์ต่อการค้นหา FTS5 จัดการสิ่งนี้โดยอัตโนมัติ\n\n## FTS5 vs Semantic Search\n\n| แง่มุม | FTS5 | Semantic Search |\n|--------|------|-----------------|\n| ความเร็ว | Sub-millisecond | 50-100ms |\n| การจับคู่ | Exact keyword | เชิงแนวคิด |\n| ทนพิมพ์ผิด | None | บางส่วน |\n| Stemming | None | โดยนัย |\n| ต้องการ embedding | ไม่ | ใช่ |\n| เหมาะกับ | คำเฉพาะ | แนวคิด |\n\nใช้ FTS5 เมื่อคุณรู้ keyword ใช้ semantic search เมื่อคุณต้องการ \"memory เกี่ยวกับ X\" โดยที่ X ถูกอธิบายต่างกัน\n\n## แนวทางปฏิบัติที่ดีที่สุด\n\n> [!TIP]\n> - **ใช้คำที่เฉพาะเจาะจง** — \"docker swarm\" ดีกว่า \"container orchestration\"\n> - **ใส่เครื่องหมายคำพูดรอบ phrase** — `\"docker swarm\"` รับประกัน phrase match\n> - **ใช้ prefix สำหรับรูปแปร** — `deploy*` จับ \"deploy\", \"deployment\", \"deploying\"\n> - **แยกสัญญาณรบกวน** — `-test` กรอง memory ทดสอบออก\n> - **รวมกับ tag** — `?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 Full-Text Search</h1>\n<p>Synapse ใช้ FTS5 (Full-Text Search 5) สำหรับการค้นหา memory ที่รวดเร็วและยืดหยุ่น เอกสารหน้านี้อธิบายวิธีการทำงานและวิธีใช้อย่างมีประสิทธิภาพ</p>\n<h2>FTS5 คืออะไร?</h2>\n<p>FTS5 เป็น SQLite extension (มีใน PostgreSQL ผ่าน extension ด้วย) ที่ให้ความสามารถ full-text search โดย:</p>\n<ul>\n<li>Index เนื้อหา text สำหรับ keyword search ที่รวดเร็ว</li>\n<li>รองรับ boolean operator (AND, OR, NOT)</li>\n<li>รองรับ phrase matching ด้วยเครื่องหมายคำพูด</li>\n<li>รองรับ prefix matching ด้วย <code>*</code></li>\n<li>จัดอันดับผลลัพธ์ตามความเกี่ยวข้อง</li>\n</ul>\n<p>Synapse ใช้ FTS5 ในการ index เนื้อหา memory ทั้งหมด เปิดใช้งานการค้นหาในระดับ sub-millisecond ทั่ว memory หลายพันรายการ</p>\n<h2>วิธีที่ Synapse ใช้ FTS5</h2>\n<p>เมื่อคุณ <code>POST /memory</code>:</p>\n<ol>\n<li>เนื้อหา memory ถูกเก็บในตาราง <code>memories</code></li>\n<li>เนื้อหายังถูกแทรกลงใน FTS5 virtual table</li>\n<li>FTS5 แบ่งคำและ index เนื้อหาโดยอัตโนมัติ</li>\n</ol>\n<p>เมื่อคุณ <code>GET /memory/search?q=...</code>:</p>\n<ol>\n<li>Synapse แยกวิเคราะห์ query โดยใช้ไวยากรณ์ FTS5</li>\n<li>ปฏิบัติการ <code>MATCH</code> กับ FTS5 index</li>\n<li>กรองตาม <code>mind_id</code> (tenant isolation)</li>\n<li>ส่งกลับผลลัพธ์ที่จัดอันดับแล้ว</li>\n</ol>\n<h2>ไวยากรณ์ Query</h2>\n<h3>ค้นหา keyword แบบง่าย</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker</code></pre><p>ส่งกลับ memory ที่มี &quot;docker&quot;</p>\n<h3>หลาย keyword (AND โดยนัย)</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker+swarm\n?q=docker%20swarm</code></pre><p>ส่งกลับ memory ที่มีทั้ง &quot;docker&quot; และ &quot;swarm&quot;</p>\n<h3>Phrase matching</h3>\n<pre><code class=\"hljs language-plaintext\">?q=&quot;docker+swarm&quot;\n?q=%22docker%20swarm%22</code></pre><p>ส่งกลับ memory ที่มี phrase &quot;docker swarm&quot; ตรงตัว</p>\n<h3>Prefix matching</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker*</code></pre><p>ส่งกลับ memory ที่มีคำขึ้นต้นด้วย &quot;docker&quot; (เช่น &quot;dockers&quot;, &quot;dockerfile&quot;, &quot;dockerize&quot;)</p>\n<h3>Boolean OR</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker+OR+kubernetes</code></pre><p>ส่งกลับ memory ที่มี &quot;docker&quot; หรือ &quot;kubernetes&quot;</p>\n<h3>Boolean NOT</h3>\n<pre><code class=\"hljs language-plaintext\">?q=docker+-swarm\n?q=docker+NOT+swarm</code></pre><p>ส่งกลับ memory ที่มี &quot;docker&quot; แต่ไม่มี &quot;swarm&quot;</p>\n<h3>การจัดกลุ่ม</h3>\n<pre><code class=\"hljs language-plaintext\">?q=(docker+OR+kubernetes)+-test</code></pre><p>ส่งกลับ memory ที่มี &quot;docker&quot; หรือ &quot;kubernetes&quot; แต่ไม่มี &quot;test&quot;</p>\n<h2>ตัวอย่างปฏิบัติ</h2>\n<h3>ค้นหา memory เกี่ยวกับโปรเจกต์</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>ค้นหา phrase ตรงตัว</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>แยก memory ทดสอบออก</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>ความถี่ของคำ (term ปรากฏบ่อยแค่ไหน)</li>\n<li>Inverse document frequency (คำที่หายากอันดับสูงกว่า)</li>\n<li>ความยาวเอกสาร (เอกสารสั้นที่มีคำนั้นอันดับสูงกว่า)</li>\n<li>น้ำหนัก column (title &gt; content)</li>\n</ul>\n<p>ผลลัพธ์ส่งกลับตามลำดับอันดับ (เกี่ยวข้องที่สุดก่อน)</p>\n<h2>ประสิทธิภาพ</h2>\n<table>\n<thead>\n<tr>\n<th>การดำเนินการ</th>\n<th>Latency</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>ค้นหา 100 memory</td>\n<td>&lt; 5ms</td>\n</tr>\n<tr>\n<td>ค้นหา 1,000 memory</td>\n<td>&lt; 10ms</td>\n</tr>\n<tr>\n<td>ค้นหา 10,000 memory</td>\n<td>&lt; 25ms</td>\n</tr>\n<tr>\n<td>ค้นหา 100,000 memory</td>\n<td>&lt; 100ms</td>\n</tr>\n</tbody></table>\n<p>FTS5 ถูกปรับให้เหมาะกับ workload ที่อ่านหนัก</p>\n<h2>ข้อจำกัด</h2>\n<h3>Stemming</h3>\n<p>FTS5 ไม่ทำ stemming โดยค่าเริ่มต้น &quot;running&quot; และ &quot;run&quot; เป็นคำต่างกัน</p>\n<p><strong>วิธีแก้:</strong> ใช้ prefix matching: <code>?q=run*</code></p>\n<h3>ความทนต่อการพิมพ์ผิด</h3>\n<p>FTS5 ไม่รองรับ fuzzy matching พิมพ์ผิดจะไม่ส่งกลับผลลัพธ์</p>\n<p><strong>วิธีแก้:</strong> ใช้ semantic search (<code>/memory/semantic-search</code>) สำหรับการจับคู่เชิงแนวคิด</p>\n<h3>Stop word</h3>\n<p>คำทั่วไป (the, a, an, is) ถูก index แต่อาจไม่มีประโยชน์ต่อการค้นหา FTS5 จัดการสิ่งนี้โดยอัตโนมัติ</p>\n<h2>FTS5 vs Semantic Search</h2>\n<table>\n<thead>\n<tr>\n<th>แง่มุม</th>\n<th>FTS5</th>\n<th>Semantic Search</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>ความเร็ว</td>\n<td>Sub-millisecond</td>\n<td>50-100ms</td>\n</tr>\n<tr>\n<td>การจับคู่</td>\n<td>Exact keyword</td>\n<td>เชิงแนวคิด</td>\n</tr>\n<tr>\n<td>ทนพิมพ์ผิด</td>\n<td>None</td>\n<td>บางส่วน</td>\n</tr>\n<tr>\n<td>Stemming</td>\n<td>None</td>\n<td>โดยนัย</td>\n</tr>\n<tr>\n<td>ต้องการ embedding</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 เมื่อคุณรู้ keyword ใช้ semantic search เมื่อคุณต้องการ &quot;memory เกี่ยวกับ X&quot; โดยที่ 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"]}