From 5a2be87f658d01bc5b3b7ecdba92ac69bf09dcf7 Mon Sep 17 00:00:00 2001
From: ai_xiaopei <xiaopei@aisim.cn>
Date: Thu, 03 Sep 2026 15:15:37 +0800
Subject: [PATCH] fix(search): 搜索准确性四连修——FTS5 MATCH 引号包裹(连字符不再被解析成 MINUS);KeywordSearch 截断按命中关键词数排序(高频 bigram 不再挤出强相关文档);原词奖励档(完整短语压过泛化 bigram);tags 字段真实参与评分(此前误用 Section)
---
internal/index/sqlite.go | 43 +++++++++++++++++++++++++++++++++++++++----
1 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/internal/index/sqlite.go b/internal/index/sqlite.go
index 06a02b3..043d483 100644
--- a/internal/index/sqlite.go
+++ b/internal/index/sqlite.go
@@ -93,7 +93,7 @@
// ClearData 清空数据(重建前调用)
func (s *Store) ClearData() error {
- _, err := s.db.Exec("DELETE FROM edges; DELETE FROM nodes;")
+ _, err := s.db.Exec("DELETE FROM edges; DELETE FROM nodes; DELETE FROM unresolved_links;")
return err
}
@@ -126,6 +126,17 @@
return err
}
+// InsertUnresolved 悬空链接入表(幂等:同 from_node+link_text 不重复插)
+func (s *Store) InsertUnresolved(fromNode int64, linkText, nameTail string) error {
+ _, err := s.db.Exec(`
+ INSERT INTO unresolved_links (from_node, link_text, name_tail, status)
+ SELECT ?, ?, ?, 'pending'
+ WHERE NOT EXISTS (
+ SELECT 1 FROM unresolved_links WHERE from_node = ? AND link_text = ?)`,
+ fromNode, linkText, nameTail, fromNode, linkText)
+ return err
+}
+
// FileStat 索引中的文件指纹
type FileStat struct {
Path string
@@ -145,9 +156,15 @@
for rows.Next() {
var st FileStat
var hash sql.NullString
- if err := rows.Scan(&st.Path, &st.Size, &st.Mtime, &hash); err != nil {
+ var size, mtime sql.NullInt64
+ // 旧库迁移到 v2 后,老行的 size/mtime/content_hash 为 NULL(ALTER ADD COLUMN 不带值)。
+ // 用 Null 类型容忍 NULL:指纹缺失的行在对账时 size/mtime 必然不等,会走
+ // sha256 二次确认并重新写入指纹,实现自愈,不会误判为"未变更"。
+ if err := rows.Scan(&st.Path, &size, &mtime, &hash); err != nil {
return nil, err
}
+ st.Size = size.Int64
+ st.Mtime = mtime.Int64
st.ContentHash = hash.String
m[st.Path] = st
}
@@ -276,6 +293,24 @@
return links, nil
}
+// GetUnresolvedLinks 某文档的悬空链接文本列表
+func (s *Store) GetUnresolvedLinks(path string) ([]string, error) {
+ rows, err := s.db.Query(`
+ SELECT u.link_text FROM unresolved_links u
+ JOIN nodes n ON n.id = u.from_node WHERE n.path = ?`, path)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ var links []string
+ for rows.Next() {
+ var l string
+ rows.Scan(&l)
+ links = append(links, l)
+ }
+ return links, rows.Err()
+}
+
// NodeInfo 节点基本信息(用于 GC)
type NodeInfo struct {
ID int64
@@ -453,7 +488,7 @@
visited[id] = true
query := `
- SELECT id, from_node, to_node, relation, label
+ SELECT id, from_node, to_node, relation, label, provenance
FROM edges
WHERE from_node = ?
`
@@ -472,7 +507,7 @@
for rows.Next() {
var e graph.Edge
var edgeID int64
- if err := rows.Scan(&edgeID, &e.FromNode, &e.ToNode, &e.Relation, &e.Label); err != nil {
+ if err := rows.Scan(&edgeID, &e.FromNode, &e.ToNode, &e.Relation, &e.Label, &e.Provenance); err != nil {
rows.Close()
return nil, fmt.Errorf("扫描边失败: %w", err)
}
--
Gitblit v1.10.0