Files
SnapAndAnaly/backend/app/services/search_utils.py
T
congsh 5c028d7952 Initial commit: snapAna 截图智能整理工具
包含 FastAPI 后端、React 前端、队列/OCR/标签/待办等完整功能。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 15:45:50 +08:00

68 lines
2.0 KiB
Python

"""截图列表搜索:FTS + 子串模糊(兼容中文标签/标题)。"""
from __future__ import annotations
from sqlalchemy import or_, select, text
from sqlalchemy.orm import Session
from app.models.meta import ScreenshotMeta
from app.models.screenshot import Screenshot
from app.models.tag import Tag
def fts_query_string(raw: str) -> str:
"""把用户输入处理成 FTS5 查询串(中英文均支持前缀匹配)。"""
parts = [p for p in raw.replace("\n", " ").split() if p]
if not parts:
return raw
cleaned: list[str] = []
for p in parts:
p = p.replace('"', "").strip()
if not p:
continue
cleaned.append(f'"{p}"*')
return " ".join(cleaned)
def collect_search_ids(session: Session, q: str, *, limit: int = 5000) -> set[int]:
"""联合 FTS5 与 LIKE 子串搜索,返回匹配的 screenshot id 集合。"""
q = q.strip()
if not q:
return set()
ids: set[int] = set()
like = f"%{q}%"
# 1) FTS5 全文索引
try:
fts_sql = text(
"SELECT rowid FROM screenshots_fts WHERE screenshots_fts MATCH :q LIMIT :lim"
)
rows = session.execute(fts_sql, {"q": fts_query_string(q), "lim": limit}).fetchall()
ids.update(int(row[0]) for row in rows)
except Exception:
pass
# 2) 子串模糊:OCR/AI 文本(解决「三花」匹配「三花猫」)
meta_ids = session.scalars(
select(ScreenshotMeta.screenshot_id).where(
or_(
ScreenshotMeta.ocr_text.ilike(like),
ScreenshotMeta.ai_title.ilike(like),
ScreenshotMeta.ai_summary.ilike(like),
ScreenshotMeta.ai_suggestion.ilike(like),
)
).limit(limit)
).all()
ids.update(int(i) for i in meta_ids)
# 3) 标签名子串匹配
tag_ids = session.scalars(
select(Screenshot.id)
.join(Screenshot.tags)
.where(Tag.name.ilike(like))
.limit(limit)
).all()
ids.update(int(i) for i in tag_ids)
return ids