# 文档搜索功能指南 ## 概述 文档搜索功能使用 Laravel Scout 和 Meilisearch 提供强大的全文搜索能力。系统会自动将转换完成的文档索引到 Meilisearch,用户可以通过关键词快速检索文档内容。 ## 核心组件 ### DocumentSearchService 文档搜索服务类,提供以下功能: 1. **search()** - 执行全文搜索 - 搜索文档标题、描述和 Markdown 内容 - 支持额外的筛选条件(类型、分组、上传者) - 自动应用用户权限过滤 2. **filterByUserPermissions()** - 权限过滤 - 确保用户只能看到有权限访问的文档 - 全局文档对所有用户可见 - 专用文档只对所属分组的用户可见 3. **prepareSearchableData()** - 准备索引数据 - 包含完整的 Markdown 内容用于搜索 - 包含文档元数据(标题、描述、类型、分组等) 4. **indexDocument()** - 索引文档 - 将文档添加到 Meilisearch 索引 - 只索引转换完成的文档 5. **updateDocumentIndex()** - 更新索引 - 更新已索引文档的信息 - 如果文档不应被索引,则移除索引 6. **removeDocumentFromIndex()** - 移除索引 - 从 Meilisearch 中删除文档索引 ### DocumentObserver 文档观察者,自动管理文档的搜索索引: - **created** - 文档创建时不立即索引(等待转换完成) - **updated** - 文档更新时检查转换状态并更新索引 - 当 conversion_status 变为 'completed' 时自动索引 - 当其他重要字段更新时也更新索引 - **deleted** - 文档删除时移除索引 - **restored** - 文档恢复时重新索引 - **forceDeleted** - 强制删除时移除索引 ## 工作流程 ### 文档索引流程 1. 用户上传 Word 文档 2. 文档保存到数据库,conversion_status 设置为 'pending' 3. 转换任务加入队列 4. 转换完成后,updateDocumentMarkdown() 将 conversion_status 更新为 'completed' 5. DocumentObserver 监听到 updated 事件 6. 自动调用 DocumentSearchService::indexDocument() 创建索引 7. 文档可以被搜索 ### 搜索流程 1. 用户输入搜索关键词 2. 调用 DocumentSearchService::search() 3. 使用 Scout 在 Meilisearch 中搜索 4. 应用额外的筛选条件 5. 使用 filterByUserPermissions() 过滤结果 6. 返回用户有权限访问的文档列表 ## 配置 ### Meilisearch 配置 在 `config/scout.php` 中配置: ```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` 文件中配置: ```env SCOUT_DRIVER=meilisearch MEILISEARCH_HOST=http://127.0.0.1:7700 MEILISEARCH_KEY=your-master-key ``` ## 使用示例 ### 基本搜索 ```php 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, ]); ``` ### 手动索引管理 ```php 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 // 重建所有文档的索引 php artisan scout:import "App\Models\Document" // 清空索引 php artisan scout:flush "App\Models\Document" ``` ## 错误处理 所有索引操作都包含错误处理: - 索引失败不会影响文档的正常保存和使用 - 所有错误都会记录到日志中 - 搜索失败时返回空集合 ## 性能考虑 1. **异步索引** - 文档转换和索引都在队列中异步处理 2. **权限过滤** - 在应用层过滤搜索结果,确保数据安全 3. **缓存策略** - 可以缓存热门搜索结果(待实现) 4. **分页** - 搜索结果应该分页显示(在前端实现) ## 故障排查 ### 文档无法被搜索 1. 检查 conversion_status 是否为 'completed' 2. 检查 Meilisearch 服务是否运行 3. 检查文档是否已索引:`php artisan scout:import "App\Models\Document"` 4. 查看日志文件中的错误信息 ### Meilisearch 连接失败 1. 确认 Meilisearch 服务正在运行 2. 检查 .env 中的 MEILISEARCH_HOST 和 MEILISEARCH_KEY 3. 测试连接:`curl http://localhost:7700/health` ### 搜索结果为空 1. 确认文档已完成转换 2. 确认用户有权限访问文档 3. 检查搜索关键词是否正确 4. 查看 Meilisearch 日志 ## 下一步 - 实现搜索页面 UI(任务 25) - 添加搜索结果高亮显示 - 实现搜索建议和自动补全 - 添加高级搜索语法支持