TL;DR: SQLite 的 FTS5 扩展在 D1 里可用,无需外部搜索服务就能提供全文检索能力。本指南覆盖 FTS5 虚拟表创建、带排序的搜索查询、结果高亮,以及与 server functions 的集成。
引言
搜索是大多数应用的核心功能。你当然可以用 Algolia 或 Meilisearch,但 D1 的 FTS5 扩展不需要额外基础设施和成本就能提供够用的全文检索。对拥有数百万文档的大多数 SaaS 应用,FTS5 就够了。要在 FTS5 之外进一步优化 D1 查询,看我们的 Cloudflare D1 查询优化指南。
FTS5 虚拟表
-- Create FTS5 index on blog posts
CREATE VIRTUAL TABLE posts_fts USING fts5(
title,
content,
excerpt,
content='posts',
content_rowid='id',
tokenize='porter unicode61'
);
-- Populate the index
INSERT INTO posts_fts(rowid, title, content, excerpt)
SELECT id, title, content, excerpt FROM posts;
搜索查询
-- Full-text search with ranking
SELECT p.id, p.title, p.excerpt,
rank AS relevance
FROM posts_fts
JOIN posts p ON posts_fts.rowid = p.id
WHERE posts_fts MATCH ?
ORDER BY rank DESC
LIMIT 20;
Server Function 集成
export const searchPostsFn = createServerFn({ method: 'GET' })
.validator(z.object({ query: z.string().min(1) }))
.handler(async ({ data }) => {
const results = await db
.selectFrom('posts_fts')
.innerJoin('posts', 'posts_fts.rowid', 'posts.id')
.where('posts_fts', 'match', data.query)
.orderBy('rank', 'desc')
.limit(20)
.execute()
return { results }
})
FTS5 功能
| 功能 | 语法 | 说明 |
|---|---|---|
| 前缀搜索 | tan* | 匹配前缀 |
| 短语搜索 | "cloudflare workers" | 精确短语 |
| 布尔运算符 | tanstack AND drizzle | 组合词项 |
| 指定列搜索 | title:tanstack | 只搜特定列 |
| NEAR 运算符 | NEAR(query, router, 5) | 邻近搜索 |
结论
D1 里的 FTS5 无需外部服务就能提供生产级全文检索。对大多数 SaaS 应用,它是替代专业搜索平台的性价比之选。想更深入理解 D1 的生产实践,看我们的 Cloudflare D1 生产指南。要在 D1 上搭完整的搜索服务,看用 D1 构建搜索即服务。