Optimize tree search with pre-built path index for O(1) vault lookup and eliminate filesystem traversal by indexing all directories and files during vault scan

This commit is contained in:
2026-03-22 23:00:35 -04:00
parent 0d60dd8acc
commit 8e1ae4be26
2 changed files with 54 additions and 46 deletions
+15 -39
View File
@@ -16,6 +16,7 @@ from backend.indexer import (
build_index,
reload_index,
index,
path_index,
get_vault_data,
get_vault_names,
find_file_in_index,
@@ -610,65 +611,40 @@ async def api_tree_search(
q: str = Query("", description="Search query"),
vault: str = Query("all", description="Vault filter"),
):
"""Search for files and directories in the tree structure.
"""Search for files and directories in the tree structure using pre-built index.
Searches through the file index for matching paths, returning
both files and their parent directories that match the query.
Uses the in-memory path index for instant filtering without filesystem access.
Args:
q: Search string to match against file/directory paths.
vault: Vault name or "all" to search everywhere.
Returns:
``TreeSearchResponse`` with matching paths and their parent directories.
``TreeSearchResponse`` with matching paths.
"""
if not q:
return {"query": q, "vault_filter": vault, "results": []}
query_lower = q.lower()
results = []
seen_paths = set() # Avoid duplicates
vaults_to_search = [vault] if vault != "all" else list(index.keys())
vaults_to_search = [vault] if vault != "all" else list(path_index.keys())
for vault_name in vaults_to_search:
vault_data = get_vault_data(vault_name)
if not vault_data:
continue
vault_root = Path(vault_data["path"])
if not vault_root.exists():
continue
vault_paths = path_index.get(vault_name, [])
for fpath in vault_root.rglob("*"):
if fpath.name.startswith("."):
continue
try:
rel_path = str(fpath.relative_to(vault_root)).replace("\\", "/")
path_lower = rel_path.lower()
name_lower = fpath.name.lower()
if query_lower not in name_lower and query_lower not in path_lower:
continue
entry_type = "directory" if fpath.is_dir() else "file"
entry_key = f"{vault_name}:{entry_type}:{rel_path}"
if entry_key in seen_paths:
continue
seen_paths.add(entry_key)
for entry in vault_paths:
path_lower = entry["path"].lower()
name_lower = entry["name"].lower()
if query_lower in name_lower or query_lower in path_lower:
results.append({
"vault": vault_name,
"path": rel_path,
"name": fpath.name,
"type": entry_type,
"matched_path": rel_path,
"path": entry["path"],
"name": entry["name"],
"type": entry["type"],
"matched_path": entry["path"],
})
except PermissionError:
continue
except Exception:
continue
return {"query": q, "vault_filter": vault, "results": results}