- 实现基于 Laravel 11 和 Filament 3.X 的文档管理系统 - 添加用户认证和分组管理功能 - 实现文档上传、分类和权限控制 - 集成 Word 文档自动转换为 Markdown - 集成 Meilisearch 全文搜索引擎 - 实现文档在线预览功能 - 添加安全日志和审计功能 - 完整的简体中文界面 - 包含完整的项目文档和部署指南 技术栈: - Laravel 11.x - Filament 3.X - Meilisearch 1.5+ - Pandoc 文档转换 - Redis 队列系统 - Pest PHP 测试框架
5.1 KiB
5.1 KiB
文档搜索功能指南
概述
文档搜索功能使用 Laravel Scout 和 Meilisearch 提供强大的全文搜索能力。系统会自动将转换完成的文档索引到 Meilisearch,用户可以通过关键词快速检索文档内容。
核心组件
DocumentSearchService
文档搜索服务类,提供以下功能:
-
search() - 执行全文搜索
- 搜索文档标题、描述和 Markdown 内容
- 支持额外的筛选条件(类型、分组、上传者)
- 自动应用用户权限过滤
-
filterByUserPermissions() - 权限过滤
- 确保用户只能看到有权限访问的文档
- 全局文档对所有用户可见
- 专用文档只对所属分组的用户可见
-
prepareSearchableData() - 准备索引数据
- 包含完整的 Markdown 内容用于搜索
- 包含文档元数据(标题、描述、类型、分组等)
-
indexDocument() - 索引文档
- 将文档添加到 Meilisearch 索引
- 只索引转换完成的文档
-
updateDocumentIndex() - 更新索引
- 更新已索引文档的信息
- 如果文档不应被索引,则移除索引
-
removeDocumentFromIndex() - 移除索引
- 从 Meilisearch 中删除文档索引
DocumentObserver
文档观察者,自动管理文档的搜索索引:
- created - 文档创建时不立即索引(等待转换完成)
- updated - 文档更新时检查转换状态并更新索引
- 当 conversion_status 变为 'completed' 时自动索引
- 当其他重要字段更新时也更新索引
- deleted - 文档删除时移除索引
- restored - 文档恢复时重新索引
- forceDeleted - 强制删除时移除索引
工作流程
文档索引流程
- 用户上传 Word 文档
- 文档保存到数据库,conversion_status 设置为 'pending'
- 转换任务加入队列
- 转换完成后,updateDocumentMarkdown() 将 conversion_status 更新为 'completed'
- DocumentObserver 监听到 updated 事件
- 自动调用 DocumentSearchService::indexDocument() 创建索引
- 文档可以被搜索
搜索流程
- 用户输入搜索关键词
- 调用 DocumentSearchService::search()
- 使用 Scout 在 Meilisearch 中搜索
- 应用额外的筛选条件
- 使用 filterByUserPermissions() 过滤结果
- 返回用户有权限访问的文档列表
配置
Meilisearch 配置
在 config/scout.php 中配置:
'meilisearch' => [
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
'key' => env('MEILISEARCH_KEY'),
'index-settings' => [
'documents' => [
'filterableAttributes' => ['type', 'group_id', 'uploaded_by', 'conversion_status'],
'sortableAttributes' => ['created_at', 'title', 'updated_at'],
'searchableAttributes' => ['title', 'description', 'markdown_content'],
],
],
],
环境变量
在 .env 文件中配置:
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=your-master-key
使用示例
基本搜索
use App\Services\DocumentSearchService;
$searchService = app(DocumentSearchService::class);
$user = auth()->user();
// 搜索关键词
$results = $searchService->search('Laravel', $user);
// 带筛选条件的搜索
$results = $searchService->search('Laravel', $user, [
'type' => 'global',
'group_id' => 1,
]);
手动索引管理
use App\Services\DocumentSearchService;
use App\Models\Document;
$searchService = app(DocumentSearchService::class);
$document = Document::find(1);
// 索引文档
$searchService->indexDocument($document);
// 更新索引
$searchService->updateDocumentIndex($document);
// 移除索引
$searchService->removeDocumentFromIndex($document);
批量重建索引
// 重建所有文档的索引
php artisan scout:import "App\Models\Document"
// 清空索引
php artisan scout:flush "App\Models\Document"
错误处理
所有索引操作都包含错误处理:
- 索引失败不会影响文档的正常保存和使用
- 所有错误都会记录到日志中
- 搜索失败时返回空集合
性能考虑
- 异步索引 - 文档转换和索引都在队列中异步处理
- 权限过滤 - 在应用层过滤搜索结果,确保数据安全
- 缓存策略 - 可以缓存热门搜索结果(待实现)
- 分页 - 搜索结果应该分页显示(在前端实现)
故障排查
文档无法被搜索
- 检查 conversion_status 是否为 'completed'
- 检查 Meilisearch 服务是否运行
- 检查文档是否已索引:
php artisan scout:import "App\Models\Document" - 查看日志文件中的错误信息
Meilisearch 连接失败
- 确认 Meilisearch 服务正在运行
- 检查 .env 中的 MEILISEARCH_HOST 和 MEILISEARCH_KEY
- 测试连接:
curl http://localhost:7700/health
搜索结果为空
- 确认文档已完成转换
- 确认用户有权限访问文档
- 检查搜索关键词是否正确
- 查看 Meilisearch 日志
下一步
- 实现搜索页面 UI(任务 25)
- 添加搜索结果高亮显示
- 实现搜索建议和自动补全
- 添加高级搜索语法支持