Files
Agent-System-Backend/internal/store/search_postgres.go
T
weichen 72e6ce66b4 Advance the core gitlink and serialize empty lists as arrays
Why: backend main pinned core 019617e (unfetchable post-migration) and the
store List* functions returned nil slices that encode as JSON null, which
crashed the frontend nav with .map on null (the 2026-09-30 white-screen).
Evidence: go test ./... across all packages; store regression
TestEmptyListsSerializeAsEmptyArrays asserts [] for empty project lists.
Impact: all 17 store list sites now initialize empty slices; build-blocker
core pin resolved; frontend no longer receives null for empty lists.
Refs: documents/records/2026-09-30-history-migration.md
2026-09-30 03:20:57 +00:00

52 lines
1.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package store
import (
core "agent-system-core"
)
// searchKnowledgePG:PG 档知识检索(设计 D16)。
// 单查询混合:tsvector('simple' 配置,词级)OR trigram LIKE 子串(中文兜底;
// LIKE 由 pg_trgm GIN 索引加速)。排序:ts_rank 优先,命中时间次之。
func (s *Store) searchKnowledgePG(owner string, q core.RetrievalQuery) ([]core.RetrievalHit, error) {
topK := q.TopK
if topK <= 0 {
topK = 5
}
text := q.Text
rows, err := s.db.Query(s.q(`
SELECT k.id,k.owner,k.project_id,k.source,k.title,k.ref,k.chunk,k.created_at,
ts_rank(k.tsv, websearch_to_tsquery('simple', ?)) AS r
FROM knowledge k
WHERE (k.owner=? OR k.owner='')
AND (? = '' OR k.tsv @@ websearch_to_tsquery('simple', ?) OR k.chunk LIKE ? OR k.title LIKE ?)
ORDER BY r DESC, k.created_at DESC
LIMIT ?`), text, owner, text, text, "%"+text+"%", "%"+text+"%", topK*2)
if err != nil {
return nil, err
}
defer rows.Close()
out := []core.RetrievalHit{}
for rows.Next() {
var d core.KnowledgeDoc
var own, ca string
var rank float64
if err := rows.Scan(&d.ID, &own, &d.ProjectID, &d.Source, &d.Title, &d.Ref, &d.Chunk, &ca, &rank); err != nil {
return nil, err
}
d.Owner = own
d.CreatedAt, _ = parseTime(ca)
if !knowledgeVisible(owner, q, d) {
continue
}
score := rank
if score == 0 {
score = 0.5 // 纯子串命中(trigram/中文兜底)给保底分
}
out = append(out, core.RetrievalHit{Doc: d, Score: score, Kind: "fulltext"})
if len(out) >= topK {
break
}
}
return out, rows.Err()
}