ModuForge Search - SQLite 搜索引擎
基于 SQLite + FTS5 的高性能树形文档搜索引擎。
✨ 特性
- ✅ 全文搜索 - SQLite FTS5 虚拟表,支持中文分词
- ✅ 树形查询 - 原生
WITH RECURSIVE 递归查询
- ✅ 结构化查询 - 完整 SQL 支持,灵活组合条件
- ✅ 增量更新 - 事务级增量索引更新
- ✅ 高并发 - WAL 模式,读写分离
- ✅ 零配置 - 内嵌 SQLite,无需额外依赖
🚀 快速开始
基本使用
use mf_search::{SqliteBackend, SearchService, SearchQuery};
use std::sync::Arc;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// 1. 创建后端
let backend = Arc::new(SqliteBackend::new_in_dir("./data/index")?);
let service = SearchService::new(backend);
// 2. 全文搜索
let results = service.search_text("富文本编辑器", 10).await?;
println!("找到 {} 条结果", results.len());
// 3. 树形查询(递归)
let results = service.query_descendants("root", 100).await?;
println!("子树节点数: {}", results.len());
// 4. 按类型查询
let results = service.query_by_type("paragraph", 20).await?;
println!("段落数: {}", results.len());
Ok(())
}
复杂查询
let results = service.search(SearchQuery {
text: Some("搜索关键词".to_string()),
node_type: Some("section".to_string()),
parent_id: Some("parent_id".to_string()),
marks: vec!["bold".to_string(), "important".to_string()],
attrs: vec![("status".to_string(), "published".to_string())],
sort_by: Some("created_at_i64".to_string()),
sort_asc: false,
limit: 20,
..Default::default()
}).await?;
与 State 集成
use mf_search::create_search_index_plugin;
use mf_state::{State, StateConfig};
let search_plugin = create_search_index_plugin("./data/index")?;
let state = State::create(StateConfig {
schema: Some(schema),
plugins: Some(vec![search_plugin]),
..Default::default()
}).await?;
// 自动索引更新
let mut tr = state.tr();
tr.add_node("root".into(), vec![node])?;
let result = state.apply(tr).await?; // 索引自动同步
📊 查询类型
1. 全文搜索
// FTS5 全文索引
SearchQuery {
text: Some("富文本编辑器".to_string()),
limit: 50,
..Default::default()
}
2. 树形递归
// 获取节点及所有子孙节点
SearchQuery {
parent_id: Some("root".to_string()),
include_descendants: true,
limit: 1000,
..Default::default()
}
3. 精确过滤
SearchQuery {
node_type: Some("paragraph".to_string()),
parent_id: Some("section_1".to_string()),
marks: vec!["bold".to_string()],
..Default::default()
}
4. 属性查询
// JSON 属性查询
SearchQuery {
attrs: vec![
("status".to_string(), "published".to_string()),
("priority".to_string(), "high".to_string()),
],
..Default::default()
}
5. 范围查询
SearchQuery {
range_field: Some("created_at_i64".to_string()),
range_min: Some(1000000),
range_max: Some(2000000),
..Default::default()
}
6. 路径前缀
// 查询路径以 "/root/section" 开头的所有节点
SearchQuery {
path_prefix: Some("/root/section".to_string()),
..Default::default()
}
🏗️ 架构
┌─────────────────────────────────────────┐
│ SearchService │ ← 高层查询接口
│ (search_text, query_descendants, ...) │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ SqliteBackend │ ← SQLite 后端
│ ┌─────────────────────────────────┐ │
│ │ nodes (主表) │ │
│ │ - 结构化数据 │ │
│ │ - B-tree 索引 │ │
│ └─────────────────────────────────┘ │
│ ┌─────────────────────────────────┐ │
│ │ nodes_fts (FTS5) │ │
│ │ - 全文索引 │ │
│ │ - 触发器自动同步 │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
🎯 性能特点
| 操作 |
性能 |
说明 |
| 全文搜索 |
~5-10ms |
FTS5 倒排索引 |
| 树形递归 |
~3ms |
WITH RECURSIVE |
| 精确过滤 |
~2ms |
B-tree 索引 |
| 批量插入 |
~50K/s |
WAL 模式 |
| 索引大小 |
1.2x |
原始数据的 1.2 倍 |
🔧 配置选项
创建选项
// 1. 指定目录
SqliteBackend::new_in_dir("./data/index")?
// 2. 系统临时目录
SqliteBackend::new_in_system_temp()?
// 3. 自定义临时根目录
SqliteBackend::new_in_temp_root("/tmp/myapp")?
查询选项
pub struct SearchQuery {
pub text: Option<String>, // 全文搜索
pub node_type: Option<String>, // 节点类型
pub parent_id: Option<String>, // 父节点
pub path_prefix: Option<String>, // 路径前缀
pub marks: Vec<String>, // 标记列表
pub attrs: Vec<(String, String)>, // 属性键值对
pub limit: usize, // 返回数量(默认 50)
pub offset: usize, // 偏移量
pub sort_by: Option<String>, // 排序字段
pub sort_asc: bool, // 排序方向
pub include_descendants: bool, // 包含子树
pub range_field: Option<String>, // 范围查询字段
pub range_min: Option<i64>, // 最小值
pub range_max: Option<i64>, // 最大值
}
🧪 测试
# 运行测试
cargo test -p moduforge-search
# 运行示例
cargo run --example basic -p moduforge-search
# 基准测试
cargo bench -p moduforge-search
📝 迁移指南
从 Tantivy 迁移到 SQLite:
- 更新依赖 - 已自动完成
- 更新代码 -
TantivyBackend → SqliteBackend
- 更新插件 -
create_tantivy_index_plugin → create_search_index_plugin
- 查询 API 兼容 -
SearchQuery 保持不变
🎁 优势对比
| 特性 |
Tantivy |
SQLite |
说明 |
| 全文搜索 |
⭐⭐⭐⭐⭐ |
⭐⭐⭐⭐ |
SQLite FTS5 足够强大 |
| 树形查询 |
⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
原生 WITH RECURSIVE |
| SQL 查询 |
❌ |
⭐⭐⭐⭐⭐ |
完整 SQL 支持 |
| 事务 |
⭐⭐ |
⭐⭐⭐⭐⭐ |
ACID 保证 |
| 维护成本 |
⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
熟悉的 SQL |
| 写入性能 |
⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
WAL 高并发 |
📚 参考