# local search query 每次重建索引导致大工作区搜索卡顿 > 状态:done > Owner:04-tree-domain / 03-rust-web > 发现日期:2026-05-27 > 来源:Sidex 全项目 review / 本地搜索性能审查 ## 现象 在 local-first 工作区中,侧边栏搜索输入虽然有前端 debounce,但后端每次 query 都会重建并写入整个 local search index。大工作区下,连续输入会触发多次递归扫描、读取 Markdown、写 `.mnote/index/search-index.json`,导致搜索和主界面卡顿。 ## 证据 - `rust/crates/mnote-web/src/routes/local_search_index.rs` - `query_local_search_index()` 第一步调用 `rebuild_local_search_index(...)`。 - `rebuild_local_search_index()` 递归 `collect_markdown_documents(...)` 后写入 index。 - 前端 `sidebar-tree-runtime.js` 的搜索渲染 debounce 不能避免后端每次 query 全盘 rebuild。 - 同文件已经存在 `refresh_local_search_index_for_path(...)` 增量更新入口,说明 watcher/单文件刷新方向已有基础,但 query path 没有复用它。 ## Sidex / VSCode 对照 Sidex / VSCode 搜索路径不会把每次 query 等价为全盘同步 rebuild: - quick access/search 使用 throttle、cache state 和 cancellation token。 - Rust search crate 有 max_results、ignore-aware、binary skip 和并行扫描。 - watcher 变化应驱动增量缓存更新,query 只消费当前 cache 或启动后台 refresh。 MNote 不需要照搬 VSCode 搜索 UI,但应采用同一原则:query path 不做强制全量重建。 ## 期望行为 - query 优先读取已有 index。 - index 缺失、版本不匹配、rootUri/workspaceId 不匹配时,才同步 rebuild。 - index 过期但仍可读时,query 返回旧 index 结果,并后台触发 refresh。 - watcher/path event 继续调用 `refresh_local_search_index_for_path(...)` 做增量更新。 - 连续输入时,旧 query 可以被取消或自然过期,不能排队多次全盘扫描。 ## 建议修复切片 1. 新增 `load_or_rebuild_local_search_index(root_path, root_uri, workspace_id)`: - 先 `read_local_search_index(root_path)`。 - 若 version/rootUri/workspaceId 匹配,直接返回 index。 - 不匹配或缺失时才调用 `rebuild_local_search_index(...)`。 2. 将 `query_local_search_index()` 改为调用 `load_or_rebuild_local_search_index(...)`。 3. 保留显式 refresh API 调用 `refresh_local_search_index(...)`。 4. 加单测: - 首次 query 会创建 index。 - 第二次 query 不改写 index `built_at`。 - refresh 后 query 能读到新内容。 - 单文件 `refresh_local_search_index_for_path(...)` 后 query 命中更新内容。 5. 后续中期再做后台 refresh、取消令牌和搜索 worker。 ## 验收 - `cargo test --manifest-path rust/Cargo.toml -p mnote-web local_search_index -- --nocapture` 通过。 - 连续两次相同 query 时,第二次不会调用 full rebuild,不更新 `built_at`。 - 侧边栏连续输入 5 个字符时,不出现 5 次全盘 rebuild。 - 大目录 smoke 中搜索响应不阻塞 FileTree 展开。 ## 修复记录 - 2026-05-27:新增 `load_or_rebuild_local_search_index(...)`,`query_local_search_index(...)` 优先读取已有匹配 version/rootUri/workspaceId 的索引;只有索引缺失、无效或 root/workspace 不匹配时才 full rebuild。 - 2026-05-27:新增回归测试 `local_search_query_reads_existing_index_without_rebuilding`,验证 query 不会看到未 refresh 的磁盘新内容,增量 refresh 后才命中新内容。 - 验证:`cargo test --manifest-path rust/Cargo.toml -p mnote-web local_search_index -- --nocapture`,4 passed。 ## 非目标 - 不在本缺陷单实现全文搜索排序重构。 - 不引入新的搜索 UI。 - 不实现全局后台 index worker;这是后续性能设计项。