mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
fix(api): handle blank search text
Signed-off-by: phernandez <paul@basicmachines.co>
This commit is contained in:
@@ -4,6 +4,8 @@ This router uses external_id UUIDs for stable, API-friendly routing.
|
||||
V1 uses string-based project names which are less efficient and less stable.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Path
|
||||
|
||||
import logfire
|
||||
@@ -74,8 +76,10 @@ async def search(
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
):
|
||||
results = await search_service.search(query, limit=page_size, offset=offset)
|
||||
total = await search_service.count(query)
|
||||
results, total = await asyncio.gather(
|
||||
search_service.search(query, limit=page_size, offset=offset),
|
||||
search_service.count(query),
|
||||
)
|
||||
except SemanticSearchDisabledError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
except SemanticDependenciesMissingError as exc:
|
||||
|
||||
@@ -1012,12 +1012,7 @@ class PostgresSearchRepository(SearchRepositoryBase):
|
||||
min_similarity: Optional[float] = None,
|
||||
) -> int:
|
||||
"""Count indexed content matching the Postgres FTS query."""
|
||||
mode = (
|
||||
retrieval_mode.value
|
||||
if isinstance(retrieval_mode, SearchRetrievalMode)
|
||||
else str(retrieval_mode)
|
||||
)
|
||||
if mode != SearchRetrievalMode.FTS.value:
|
||||
if retrieval_mode != SearchRetrievalMode.FTS:
|
||||
return await super().count(
|
||||
search_text=search_text,
|
||||
permalink=permalink,
|
||||
|
||||
@@ -261,6 +261,9 @@ class SearchRepositoryBase(ABC):
|
||||
min_similarity: Optional[float] = None,
|
||||
) -> int:
|
||||
"""Count results for retrieval modes that cannot use a backend COUNT query."""
|
||||
# Trigger: vector and hybrid modes rank after embedding lookup, filtering, and fusion.
|
||||
# Why: that scoring pipeline is not expressible as a portable database COUNT query.
|
||||
# Outcome: fetch the bounded candidate set and count the final in-memory results.
|
||||
results = await self.search(
|
||||
search_text=search_text,
|
||||
permalink=permalink,
|
||||
|
||||
@@ -1031,12 +1031,7 @@ class SQLiteSearchRepository(SearchRepositoryBase):
|
||||
min_similarity: Optional[float] = None,
|
||||
) -> int:
|
||||
"""Count indexed content matching the SQLite FTS query."""
|
||||
mode = (
|
||||
retrieval_mode.value
|
||||
if isinstance(retrieval_mode, SearchRetrievalMode)
|
||||
else str(retrieval_mode)
|
||||
)
|
||||
if mode != SearchRetrievalMode.FTS.value:
|
||||
if retrieval_mode != SearchRetrievalMode.FTS:
|
||||
return await super().count(
|
||||
search_text=search_text,
|
||||
permalink=permalink,
|
||||
|
||||
@@ -155,10 +155,10 @@ class SearchService:
|
||||
tags = query.tags
|
||||
|
||||
# Support tag:<tag> shorthand by mapping to tags filter.
|
||||
if search_text:
|
||||
text = search_text.strip()
|
||||
if text.lower().startswith("tag:"):
|
||||
tag_values = re.split(r"[,\s]+", text[4:].strip())
|
||||
if search_text is not None:
|
||||
search_text = search_text.strip() or None
|
||||
if search_text and search_text.lower().startswith("tag:"):
|
||||
tag_values = re.split(r"[,\s]+", search_text[4:].strip())
|
||||
parsed_tags = [t for t in tag_values if t]
|
||||
if parsed_tags:
|
||||
tags = parsed_tags
|
||||
|
||||
Reference in New Issue
Block a user