# ModuForge Search - SQLite 搜索引擎
基于 SQLite + FTS5 的高性能树形文档搜索引擎。
## ✨ 特性
- ✅ **全文搜索** - SQLite FTS5 虚拟表,支持中文分词
- ✅ **树形查询** - 原生 `WITH RECURSIVE` 递归查询
- ✅ **结构化查询** - 完整 SQL 支持,灵活组合条件
- ✅ **增量更新** - 事务级增量索引更新
- ✅ **高并发** - WAL 模式,读写分离
- ✅ **零配置** - 内嵌 SQLite,无需额外依赖
## 🚀 快速开始
### 基本使用
```rust
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(())
}
```
### 复杂查询
```rust
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 集成
```rust
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. 全文搜索
```rust
// FTS5 全文索引
SearchQuery {
text: Some("富文本编辑器".to_string()),
limit: 50,
..Default::default()
}
```
### 2. 树形递归
```rust
// 获取节点及所有子孙节点
SearchQuery {
parent_id: Some("root".to_string()),
include_descendants: true,
limit: 1000,
..Default::default()
}
```
### 3. 精确过滤
```rust
SearchQuery {
node_type: Some("paragraph".to_string()),
parent_id: Some("section_1".to_string()),
marks: vec!["bold".to_string()],
..Default::default()
}
```
### 4. 属性查询
```rust
// JSON 属性查询
SearchQuery {
attrs: vec![
("status".to_string(), "published".to_string()),
("priority".to_string(), "high".to_string()),
],
..Default::default()
}
```
### 5. 范围查询
```rust
SearchQuery {
range_field: Some("created_at_i64".to_string()),
range_min: Some(1000000),
range_max: Some(2000000),
..Default::default()
}
```
### 6. 路径前缀
```rust
// 查询路径以 "/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 倍 |
## 🔧 配置选项
### 创建选项
```rust
// 1. 指定目录
SqliteBackend::new_in_dir("./data/index")?
// 2. 系统临时目录
SqliteBackend::new_in_system_temp()?
// 3. 自定义临时根目录
SqliteBackend::new_in_temp_root("/tmp/myapp")?
```
### 查询选项
```rust
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>, // 最大值
}
```
## 🧪 测试
```bash
# 运行测试
cargo test -p moduforge-search
# 运行示例
cargo run --example basic -p moduforge-search
# 基准测试
cargo bench -p moduforge-search
```
## 📝 迁移指南
从 Tantivy 迁移到 SQLite:
1. **更新依赖** - 已自动完成
2. **更新代码** - `TantivyBackend` → `SqliteBackend`
3. **更新插件** - `create_tantivy_index_plugin` → `create_search_index_plugin`
4. **查询 API 兼容** - `SearchQuery` 保持不变
## 🎁 优势对比
| 全文搜索 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | SQLite FTS5 足够强大 |
| 树形查询 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 原生 WITH RECURSIVE |
| SQL 查询 | ❌ | ⭐⭐⭐⭐⭐ | 完整 SQL 支持 |
| 事务 | ⭐⭐ | ⭐⭐⭐⭐⭐ | ACID 保证 |
| 维护成本 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 熟悉的 SQL |
| 写入性能 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | WAL 高并发 |
## 📚 参考
- [SQLite FTS5](https://www.sqlite.org/fts5.html)
- [Recursive CTE](https://www.sqlite.org/lang_with.html)
- [rusqlite](https://docs.rs/rusqlite/)