From 960a60ac4c681bfbcb3d94b34be616af2f0b3152 Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Sun, 2 Oct 2022 11:17:12 +0800 Subject: [PATCH 1/4] =?UTF-8?q?:sparkles:=20=E7=BC=96=E8=BE=91=E5=99=A8?= =?UTF-8?q?=E5=BC=8F=E5=8F=8D=E9=93=BE=E9=9D=A2=E6=9D=BF=20https://github.?= =?UTF-8?q?com/siyuan-note/siyuan/issues/3565?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/model/backlink.go | 104 +----------------- kernel/model/block.go | 20 ++-- kernel/model/path.go | 228 --------------------------------------- 3 files changed, 15 insertions(+), 337 deletions(-) diff --git a/kernel/model/backlink.go b/kernel/model/backlink.go index 918abb8be..bea645cf6 100644 --- a/kernel/model/backlink.go +++ b/kernel/model/backlink.go @@ -384,116 +384,22 @@ func buildBacklink(refID string, refTree *parse.Tree, luteEngine *lute.Lute) (re return } -func BuildTreeBacklink(id, keyword, mentionKeyword string, beforeLen int) (boxID string, linkPaths, mentionPaths []*Path, linkRefsCount, mentionsCount int) { - linkPaths = []*Path{} - mentionPaths = []*Path{} +func BuildTreeBacklink(id, keyword, mentionKeyword string, beforeLen int) (boxID string, backlinks, backmentions []*Block, linkRefsCount, mentionsCount int) { + backlinks, backmentions = []*Block{}, []*Block{} sqlBlock := sql.GetBlock(id) if nil == sqlBlock { return } - rootID := sqlBlock.RootID boxID = sqlBlock.Box - var links []*Block refs := sql.QueryRefsByDefID(id, true) refs = removeDuplicatedRefs(refs) // 同一个块中引用多个相同块时反链去重 https://github.com/siyuan-note/siyuan/issues/3317 - // 为了减少查询,组装好 IDs 后一次查出 - defSQLBlockIDs, refSQLBlockIDs := map[string]bool{}, map[string]bool{} - var queryBlockIDs []string - for _, ref := range refs { - defSQLBlockIDs[ref.DefBlockID] = true - refSQLBlockIDs[ref.BlockID] = true - queryBlockIDs = append(queryBlockIDs, ref.DefBlockID) - queryBlockIDs = append(queryBlockIDs, ref.BlockID) - } - querySQLBlocks := sql.GetBlocks(queryBlockIDs) - defSQLBlocksCache := map[string]*sql.Block{} - for _, defSQLBlock := range querySQLBlocks { - if nil != defSQLBlock && defSQLBlockIDs[defSQLBlock.ID] { - defSQLBlocksCache[defSQLBlock.ID] = defSQLBlock - } - } - refSQLBlocksCache := map[string]*sql.Block{} - for _, refSQLBlock := range querySQLBlocks { - if nil != refSQLBlock && refSQLBlockIDs[refSQLBlock.ID] { - refSQLBlocksCache[refSQLBlock.ID] = refSQLBlock - } - } + backlinks, excludeBacklinkIDs := buildLinkRefs(id, refs) - excludeBacklinkIDs := hashset.New() - for _, ref := range refs { - defSQLBlock := defSQLBlocksCache[(ref.DefBlockID)] - if nil == defSQLBlock { - continue - } - - refSQLBlock := refSQLBlocksCache[ref.BlockID] - if nil == refSQLBlock { - continue - } - refBlock := fromSQLBlock(refSQLBlock, "", beforeLen) - if rootID == refBlock.RootID { // 排除当前文档内引用提及 - excludeBacklinkIDs.Add(refBlock.RootID, refBlock.ID) - } - defBlock := fromSQLBlock(defSQLBlock, "", beforeLen) - if defBlock.RootID == rootID { // 当前文档的定义块 - links = append(links, defBlock) - if ref.DefBlockID == defBlock.ID { - defBlock.Refs = append(defBlock.Refs, refBlock) - } - } - } - - for _, link := range links { - for _, ref := range link.Refs { - excludeBacklinkIDs.Add(ref.RootID, ref.ID) - } - linkRefsCount += len(link.Refs) - } - - var linkRefs []*Block - processedParagraphs := hashset.New() - var paragraphParentIDs []string - for _, link := range links { - for _, ref := range link.Refs { - if "NodeParagraph" == ref.Type { - paragraphParentIDs = append(paragraphParentIDs, ref.ParentID) - } - } - } - paragraphParents := sql.GetBlocks(paragraphParentIDs) - for _, p := range paragraphParents { - if "i" == p.Type || "h" == p.Type { - linkRefs = append(linkRefs, fromSQLBlock(p, keyword, beforeLen)) - processedParagraphs.Add(p.ID) - } - } - for _, link := range links { - for _, ref := range link.Refs { - if "NodeParagraph" == ref.Type { - if processedParagraphs.Contains(ref.ParentID) { - continue - } - } - - ref.DefID = link.ID - ref.DefPath = link.Path - - content := ref.Content - if "" != keyword { - _, content = search.MarkText(content, keyword, beforeLen, Conf.Search.CaseSensitive) - ref.Content = content - } - linkRefs = append(linkRefs, ref) - } - } - linkPaths = toSubTree(linkRefs, keyword) - - mentions := buildTreeBackmention(sqlBlock, linkRefs, mentionKeyword, excludeBacklinkIDs, beforeLen) - mentionsCount = len(mentions) - mentionPaths = toFlatTree(mentions, 0, "backlink") + backmentions = buildTreeBackmention(sqlBlock, backlinks, mentionKeyword, excludeBacklinkIDs, beforeLen) + mentionsCount = len(backmentions) return } diff --git a/kernel/model/block.go b/kernel/model/block.go index 90108d10b..ce5e50e1f 100644 --- a/kernel/model/block.go +++ b/kernel/model/block.go @@ -64,16 +64,16 @@ func (block *Block) IsContainerBlock() bool { } type Path struct { - ID string `json:"id"` // 块 ID - Box string `json:"box"` // 块 Box - Name string `json:"name"` // 当前路径 - Type string `json:"type"` // "path" - NodeType string `json:"nodeType"` // 节点类型 - SubType string `json:"subType"` // 节点子类型 - Blocks []*Block `json:"blocks"` // 子块节点 - Children []*Path `json:"children"` // 子路径节点 - Depth int `json:"depth"` // 层级深度 - Count int `json:"count"` // 子块计数 + ID string `json:"id"` // 块 ID + Box string `json:"box"` // 块 Box + Name string `json:"name"` // 当前路径 + Type string `json:"type"` // "path" + NodeType string `json:"nodeType"` // 节点类型 + SubType string `json:"subType"` // 节点子类型 + Blocks []*Block `json:"blocks,omitempty"` // 子块节点 + Children []*Path `json:"children,omitempty"` // 子路径节点 + Depth int `json:"depth"` // 层级深度 + Count int `json:"count"` // 子块计数 } func RecentUpdatedBlocks() (ret []*Block) { diff --git a/kernel/model/path.go b/kernel/model/path.go index 6814911cc..4f754c99d 100644 --- a/kernel/model/path.go +++ b/kernel/model/path.go @@ -27,8 +27,6 @@ import ( "github.com/88250/gulu" "github.com/88250/lute/ast" "github.com/siyuan-note/logging" - "github.com/siyuan-note/siyuan/kernel/search" - "github.com/siyuan-note/siyuan/kernel/sql" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -125,232 +123,6 @@ func toFlatTree(blocks []*Block, baseDepth int, typ string) (ret []*Path) { return } -func toSubTree(blocks []*Block, keyword string) (ret []*Path) { - keyword = strings.TrimSpace(keyword) - var blockRoots []*Block - for _, block := range blocks { - root := getBlockIn(blockRoots, block.RootID) - if nil == root { - root, _ = getBlock(block.RootID) - blockRoots = append(blockRoots, root) - } - block.Depth = 1 - block.Count = len(block.Children) - root.Children = append(root.Children, block) - } - - for _, root := range blockRoots { - treeNode := &Path{ - ID: root.ID, - Box: root.Box, - Name: path.Base(root.HPath), - Type: "backlink", - NodeType: "NodeDocument", - SubType: root.SubType, - Depth: 0, - Count: len(root.Children), - } - for _, c := range root.Children { - if "NodeListItem" == c.Type { - tree, _ := loadTreeByBlockID(c.RootID) - li := treenode.GetNodeInTree(tree, c.ID) - if nil == li || nil == li.FirstChild { - // 反链面板拖拽到文档以后可能会出现这种情况 https://github.com/siyuan-note/siyuan/issues/5363 - continue - } - - var first *sql.Block - if 3 != li.ListData.Typ { - first = sql.GetBlock(li.FirstChild.ID) - } else { - first = sql.GetBlock(li.FirstChild.Next.ID) - } - name := first.Content - parentPos := 0 - if "" != keyword { - parentPos, name = search.MarkText(name, keyword, 12, Conf.Search.CaseSensitive) - } - subRoot := &Path{ - ID: li.ID, - Box: li.Box, - Name: name, - Type: "backlink", - NodeType: li.Type.String(), - SubType: c.SubType, - Depth: 1, - Count: 1, - } - - unfold := true - for liFirstBlockSpan := li.FirstChild.FirstChild; nil != liFirstBlockSpan; liFirstBlockSpan = liFirstBlockSpan.Next { - if treenode.IsBlockRef(liFirstBlockSpan) { - continue - } - if "" != strings.TrimSpace(liFirstBlockSpan.Text()) { - unfold = false - break - } - } - for next := li.FirstChild.Next; nil != next; next = next.Next { - subBlock, _ := getBlock(next.ID) - if unfold { - if ast.NodeList == next.Type { - for subLi := next.FirstChild; nil != subLi; subLi = subLi.Next { - subLiBlock, _ := getBlock(subLi.ID) - var subFirst *sql.Block - if 3 != subLi.ListData.Typ { - subFirst = sql.GetBlock(subLi.FirstChild.ID) - } else { - subFirst = sql.GetBlock(subLi.FirstChild.Next.ID) - } - subPos := 0 - content := subFirst.Content - if "" != keyword { - subPos, content = search.MarkText(subFirst.Content, keyword, 12, Conf.Search.CaseSensitive) - } - if -1 < subPos { - parentPos = 0 // 需要显示父级 - } - subLiBlock.Content = content - subLiBlock.Depth = 2 - subRoot.Blocks = append(subRoot.Blocks, subLiBlock) - } - } else if ast.NodeHeading == next.Type { - subBlock.Depth = 2 - subRoot.Blocks = append(subRoot.Blocks, subBlock) - headingChildren := treenode.HeadingChildren(next) - var breakSub bool - for _, n := range headingChildren { - block, _ := getBlock(n.ID) - subPos := 0 - content := block.Content - if "" != keyword { - subPos, content = search.MarkText(block.Content, keyword, 12, Conf.Search.CaseSensitive) - } - if -1 < subPos { - parentPos = 0 - } - block.Content = content - block.Depth = 3 - subRoot.Blocks = append(subRoot.Blocks, block) - if ast.NodeHeading == n.Type { - // 跳过子标题下面的块 - breakSub = true - break - } - } - if breakSub { - break - } - } else { - if nil == treenode.HeadingParent(next) { - subBlock.Depth = 2 - subRoot.Blocks = append(subRoot.Blocks, subBlock) - } - } - } - } - if -1 < parentPos { - treeNode.Children = append(treeNode.Children, subRoot) - } - } else if "NodeHeading" == c.Type { - tree, _ := loadTreeByBlockID(c.RootID) - h := treenode.GetNodeInTree(tree, c.ID) - if nil == h { - continue - } - - name := sql.GetBlock(h.ID).Content - parentPos := 0 - if "" != keyword { - parentPos, name = search.MarkText(name, keyword, 12, Conf.Search.CaseSensitive) - } - subRoot := &Path{ - ID: h.ID, - Box: h.Box, - Name: name, - Type: "backlink", - NodeType: h.Type.String(), - SubType: c.SubType, - Depth: 1, - Count: 1, - } - - unfold := true - for headingFirstSpan := h.FirstChild; nil != headingFirstSpan; headingFirstSpan = headingFirstSpan.Next { - if treenode.IsBlockRef(headingFirstSpan) { - continue - } - if "" != strings.TrimSpace(headingFirstSpan.Text()) { - unfold = false - break - } - } - - if unfold { - headingChildren := treenode.HeadingChildren(h) - for _, headingChild := range headingChildren { - if ast.NodeList == headingChild.Type { - for subLi := headingChild.FirstChild; nil != subLi; subLi = subLi.Next { - subLiBlock, _ := getBlock(subLi.ID) - var subFirst *sql.Block - if 3 != subLi.ListData.Typ { - subFirst = sql.GetBlock(subLi.FirstChild.ID) - } else { - subFirst = sql.GetBlock(subLi.FirstChild.Next.ID) - } - subPos := 0 - content := subFirst.Content - if "" != keyword { - subPos, content = search.MarkText(content, keyword, 12, Conf.Search.CaseSensitive) - } - if -1 < subPos { - parentPos = 0 - } - subLiBlock.Content = subFirst.Content - subLiBlock.Depth = 2 - subRoot.Blocks = append(subRoot.Blocks, subLiBlock) - } - } else { - subBlock, _ := getBlock(headingChild.ID) - subBlock.Depth = 2 - subRoot.Blocks = append(subRoot.Blocks, subBlock) - } - } - } - - if -1 < parentPos { - treeNode.Children = append(treeNode.Children, subRoot) - } - } else { - pos := 0 - content := c.Content - if "" != keyword { - pos, content = search.MarkText(content, keyword, 12, Conf.Search.CaseSensitive) - } - if -1 < pos { - treeNode.Blocks = append(treeNode.Blocks, c) - } - } - } - - rootPos := -1 - var rootContent string - if "" != keyword { - rootPos, rootContent = search.MarkText(treeNode.Name, keyword, 12, Conf.Search.CaseSensitive) - treeNode.Name = rootContent - } - if 0 < len(treeNode.Children) || 0 < len(treeNode.Blocks) || (-1 < rootPos && "" != keyword) { - ret = append(ret, treeNode) - } - } - - sort.Slice(ret, func(i, j int) bool { - return ret[i].ID > ret[j].ID - }) - return -} - func getBlockIn(blocks []*Block, id string) *Block { if "" == id { return nil From fcaddd6966c446634fee663b319249c73e27ad4c Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Sun, 2 Oct 2022 11:21:37 +0800 Subject: [PATCH 2/4] =?UTF-8?q?:sparkles:=20=E7=BC=96=E8=BE=91=E5=99=A8?= =?UTF-8?q?=E5=BC=8F=E5=8F=8D=E9=93=BE=E9=9D=A2=E6=9D=BF=20https://github.?= =?UTF-8?q?com/siyuan-note/siyuan/issues/3565?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/model/backlink.go | 10 +++++---- kernel/model/path.go | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/kernel/model/backlink.go b/kernel/model/backlink.go index bea645cf6..2e1bf2d06 100644 --- a/kernel/model/backlink.go +++ b/kernel/model/backlink.go @@ -384,8 +384,8 @@ func buildBacklink(refID string, refTree *parse.Tree, luteEngine *lute.Lute) (re return } -func BuildTreeBacklink(id, keyword, mentionKeyword string, beforeLen int) (boxID string, backlinks, backmentions []*Block, linkRefsCount, mentionsCount int) { - backlinks, backmentions = []*Block{}, []*Block{} +func BuildTreeBacklink(id, keyword, mentionKeyword string, beforeLen int) (boxID string, backlinks, backmentions []*Path, linkRefsCount, mentionsCount int) { + backlinks, backmentions = []*Path{}, []*Path{} sqlBlock := sql.GetBlock(id) if nil == sqlBlock { @@ -396,9 +396,11 @@ func BuildTreeBacklink(id, keyword, mentionKeyword string, beforeLen int) (boxID refs := sql.QueryRefsByDefID(id, true) refs = removeDuplicatedRefs(refs) // 同一个块中引用多个相同块时反链去重 https://github.com/siyuan-note/siyuan/issues/3317 - backlinks, excludeBacklinkIDs := buildLinkRefs(id, refs) + linkRefs, excludeBacklinkIDs := buildLinkRefs(id, refs) + backlinks = toSubTree(linkRefs, keyword) - backmentions = buildTreeBackmention(sqlBlock, backlinks, mentionKeyword, excludeBacklinkIDs, beforeLen) + mentionRefs := buildTreeBackmention(sqlBlock, linkRefs, mentionKeyword, excludeBacklinkIDs, beforeLen) + backmentions = toFlatTree(mentionRefs, 0, "backlink") mentionsCount = len(backmentions) return } diff --git a/kernel/model/path.go b/kernel/model/path.go index 4f754c99d..37c89b1c7 100644 --- a/kernel/model/path.go +++ b/kernel/model/path.go @@ -27,6 +27,7 @@ import ( "github.com/88250/gulu" "github.com/88250/lute/ast" "github.com/siyuan-note/logging" + "github.com/siyuan-note/siyuan/kernel/search" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -123,6 +124,49 @@ func toFlatTree(blocks []*Block, baseDepth int, typ string) (ret []*Path) { return } +func toSubTree(blocks []*Block, keyword string) (ret []*Path) { + keyword = strings.TrimSpace(keyword) + var blockRoots []*Block + for _, block := range blocks { + root := getBlockIn(blockRoots, block.RootID) + if nil == root { + root, _ = getBlock(block.RootID) + blockRoots = append(blockRoots, root) + } + block.Depth = 1 + block.Count = len(block.Children) + root.Children = append(root.Children, block) + } + + for _, root := range blockRoots { + treeNode := &Path{ + ID: root.ID, + Box: root.Box, + Name: path.Base(root.HPath), + Type: "backlink", + NodeType: "NodeDocument", + SubType: root.SubType, + Depth: 0, + Count: len(root.Children), + } + + rootPos := -1 + var rootContent string + if "" != keyword { + rootPos, rootContent = search.MarkText(treeNode.Name, keyword, 12, Conf.Search.CaseSensitive) + treeNode.Name = rootContent + } + if 0 < len(treeNode.Children) || 0 < len(treeNode.Blocks) || (-1 < rootPos && "" != keyword) { + ret = append(ret, treeNode) + } + } + + sort.Slice(ret, func(i, j int) bool { + return ret[i].ID > ret[j].ID + }) + return +} + func getBlockIn(blocks []*Block, id string) *Block { if "" == id { return nil From d19cd19f44f1b522781dcfd5a27366f8c6b88be5 Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Sun, 2 Oct 2022 11:27:56 +0800 Subject: [PATCH 3/4] =?UTF-8?q?:sparkles:=20=E7=BC=96=E8=BE=91=E5=99=A8?= =?UTF-8?q?=E5=BC=8F=E5=8F=8D=E9=93=BE=E9=9D=A2=E6=9D=BF=20https://github.?= =?UTF-8?q?com/siyuan-note/siyuan/issues/3565?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/model/backlink.go | 8 +++++++- kernel/model/path.go | 44 ---------------------------------------- 2 files changed, 7 insertions(+), 45 deletions(-) diff --git a/kernel/model/backlink.go b/kernel/model/backlink.go index 2e1bf2d06..a5a84b2f1 100644 --- a/kernel/model/backlink.go +++ b/kernel/model/backlink.go @@ -397,10 +397,16 @@ func BuildTreeBacklink(id, keyword, mentionKeyword string, beforeLen int) (boxID refs = removeDuplicatedRefs(refs) // 同一个块中引用多个相同块时反链去重 https://github.com/siyuan-note/siyuan/issues/3317 linkRefs, excludeBacklinkIDs := buildLinkRefs(id, refs) - backlinks = toSubTree(linkRefs, keyword) + backlinks = toFlatTree(linkRefs, 0, "backlink") + for _, l := range backlinks { + l.Blocks = nil + } mentionRefs := buildTreeBackmention(sqlBlock, linkRefs, mentionKeyword, excludeBacklinkIDs, beforeLen) backmentions = toFlatTree(mentionRefs, 0, "backlink") + for _, l := range backmentions { + l.Blocks = nil + } mentionsCount = len(backmentions) return } diff --git a/kernel/model/path.go b/kernel/model/path.go index 37c89b1c7..4f754c99d 100644 --- a/kernel/model/path.go +++ b/kernel/model/path.go @@ -27,7 +27,6 @@ import ( "github.com/88250/gulu" "github.com/88250/lute/ast" "github.com/siyuan-note/logging" - "github.com/siyuan-note/siyuan/kernel/search" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -124,49 +123,6 @@ func toFlatTree(blocks []*Block, baseDepth int, typ string) (ret []*Path) { return } -func toSubTree(blocks []*Block, keyword string) (ret []*Path) { - keyword = strings.TrimSpace(keyword) - var blockRoots []*Block - for _, block := range blocks { - root := getBlockIn(blockRoots, block.RootID) - if nil == root { - root, _ = getBlock(block.RootID) - blockRoots = append(blockRoots, root) - } - block.Depth = 1 - block.Count = len(block.Children) - root.Children = append(root.Children, block) - } - - for _, root := range blockRoots { - treeNode := &Path{ - ID: root.ID, - Box: root.Box, - Name: path.Base(root.HPath), - Type: "backlink", - NodeType: "NodeDocument", - SubType: root.SubType, - Depth: 0, - Count: len(root.Children), - } - - rootPos := -1 - var rootContent string - if "" != keyword { - rootPos, rootContent = search.MarkText(treeNode.Name, keyword, 12, Conf.Search.CaseSensitive) - treeNode.Name = rootContent - } - if 0 < len(treeNode.Children) || 0 < len(treeNode.Blocks) || (-1 < rootPos && "" != keyword) { - ret = append(ret, treeNode) - } - } - - sort.Slice(ret, func(i, j int) bool { - return ret[i].ID > ret[j].ID - }) - return -} - func getBlockIn(blocks []*Block, id string) *Block { if "" == id { return nil From 7682cc447b5b1b4e43bb4e3adc37bf4d052f915c Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Sun, 2 Oct 2022 11:36:02 +0800 Subject: [PATCH 4/4] =?UTF-8?q?:sparkles:=20=E7=BC=96=E8=BE=91=E5=99=A8?= =?UTF-8?q?=E5=BC=8F=E5=8F=8D=E9=93=BE=E9=9D=A2=E6=9D=BF=20https://github.?= =?UTF-8?q?com/siyuan-note/siyuan/issues/3565?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/model/backlink.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/model/backlink.go b/kernel/model/backlink.go index a5a84b2f1..cea5d30d5 100644 --- a/kernel/model/backlink.go +++ b/kernel/model/backlink.go @@ -176,7 +176,7 @@ func GetBackmentionDoc(defID, refTreeID, keyword string) (ret []*Backlink) { refs := sql.QueryRefsByDefID(defID, true) refs = removeDuplicatedRefs(refs) // 同一个块中引用多个相同块时反链去重 https://github.com/siyuan-note/siyuan/issues/3317 - linkRefs, excludeBacklinkIDs := buildLinkRefs(rootID, refs) + linkRefs, _, excludeBacklinkIDs := buildLinkRefs(rootID, refs) tmpMentions := buildTreeBackmention(sqlBlock, linkRefs, keyword, excludeBacklinkIDs, beforeLen) luteEngine := NewLute() treeCache := map[string]*parse.Tree{} @@ -221,7 +221,7 @@ func GetBacklinkDoc(defID, refTreeID string) (ret []*Backlink) { } refs = removeDuplicatedRefs(refs) // 同一个块中引用多个相同块时反链去重 https://github.com/siyuan-note/siyuan/issues/3317 - linkRefs, _ := buildLinkRefs(rootID, refs) + linkRefs, _, _ := buildLinkRefs(rootID, refs) refTree, err := loadTreeByBlockID(refTreeID) if nil != err { logging.LogWarnf("load ref tree [%s] failed: %s", refTreeID, err) @@ -236,7 +236,7 @@ func GetBacklinkDoc(defID, refTreeID string) (ret []*Backlink) { return } -func buildLinkRefs(defRootID string, refs []*sql.Ref) (ret []*Block, excludeBacklinkIDs *hashset.Set) { +func buildLinkRefs(defRootID string, refs []*sql.Ref) (ret []*Block, refsCount int, excludeBacklinkIDs *hashset.Set) { // 为了减少查询,组装好 IDs 后一次查出 defSQLBlockIDs, refSQLBlockIDs := map[string]bool{}, map[string]bool{} var queryBlockIDs []string @@ -289,6 +289,7 @@ func buildLinkRefs(defRootID string, refs []*sql.Ref) (ret []*Block, excludeBack for _, ref := range link.Refs { excludeBacklinkIDs.Add(ref.RootID, ref.ID) } + refsCount += len(link.Refs) } processedParagraphs := hashset.New() @@ -396,7 +397,7 @@ func BuildTreeBacklink(id, keyword, mentionKeyword string, beforeLen int) (boxID refs := sql.QueryRefsByDefID(id, true) refs = removeDuplicatedRefs(refs) // 同一个块中引用多个相同块时反链去重 https://github.com/siyuan-note/siyuan/issues/3317 - linkRefs, excludeBacklinkIDs := buildLinkRefs(id, refs) + linkRefs, linkRefsCount, excludeBacklinkIDs := buildLinkRefs(id, refs) backlinks = toFlatTree(linkRefs, 0, "backlink") for _, l := range backlinks { l.Blocks = nil