diff --git a/kernel/av/mirror.go b/kernel/av/mirror.go index 24f02ef18..8814d8f56 100644 --- a/kernel/av/mirror.go +++ b/kernel/av/mirror.go @@ -6,6 +6,7 @@ import ( "sync" "github.com/88250/gulu" + "github.com/88250/lute/ast" "github.com/siyuan-note/filelock" "github.com/siyuan-note/logging" "github.com/siyuan-note/siyuan/kernel/util" @@ -16,6 +17,30 @@ var ( AttributeViewBlocksLock = sync.Mutex{} ) +func GetBlockRels() (ret map[string][]string) { + AttributeViewBlocksLock.Lock() + defer AttributeViewBlocksLock.Unlock() + + ret = map[string][]string{} + + blocks := filepath.Join(util.DataDir, "storage", "av", "blocks.msgpack") + if !filelock.IsExist(blocks) { + return + } + + data, err := filelock.ReadFile(blocks) + if nil != err { + logging.LogErrorf("read attribute view blocks failed: %s", err) + return + } + + if err = msgpack.Unmarshal(data, &ret); nil != err { + logging.LogErrorf("unmarshal attribute view blocks failed: %s", err) + return + } + return +} + func IsMirror(avID string) bool { AttributeViewBlocksLock.Lock() defer AttributeViewBlocksLock.Unlock() @@ -86,6 +111,56 @@ func RemoveBlockRel(avID, blockID string) { } } +func BatchUpsertBlockRel(nodes []*ast.Node) { + AttributeViewBlocksLock.Lock() + defer AttributeViewBlocksLock.Unlock() + + avBlocks := map[string][]string{} + blocks := filepath.Join(util.DataDir, "storage", "av", "blocks.msgpack") + if !filelock.IsExist(blocks) { + if err := os.MkdirAll(filepath.Dir(blocks), 0755); nil != err { + logging.LogErrorf("create attribute view dir failed: %s", err) + return + } + } else { + data, err := filelock.ReadFile(blocks) + if nil != err { + logging.LogErrorf("read attribute view blocks failed: %s", err) + return + } + + if err = msgpack.Unmarshal(data, &avBlocks); nil != err { + logging.LogErrorf("unmarshal attribute view blocks failed: %s", err) + return + } + } + + for _, n := range nodes { + if ast.NodeAttributeView != n.Type { + continue + } + + if "" == n.AttributeViewID || "" == n.ID { + continue + } + + blockIDs := avBlocks[n.AttributeViewID] + blockIDs = append(blockIDs, n.ID) + blockIDs = gulu.Str.RemoveDuplicatedElem(blockIDs) + avBlocks[n.AttributeViewID] = blockIDs + } + + data, err := msgpack.Marshal(avBlocks) + if nil != err { + logging.LogErrorf("marshal attribute view blocks failed: %s", err) + return + } + if err = filelock.WriteFile(blocks, data); nil != err { + logging.LogErrorf("write attribute view blocks failed: %s", err) + return + } +} + func UpsertBlockRel(avID, blockID string) { AttributeViewBlocksLock.Lock() defer AttributeViewBlocksLock.Unlock() diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 33b65ea81..39a548896 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -208,7 +208,7 @@ func SearchAttributeView(keyword string) (ret []*SearchAttributeViewResult) { logging.LogErrorf("read directory [%s] failed: %s", avDir, err) return } - + avBlockRels := av.GetBlockRels() for _, entry := range entries { if entry.IsDir() { continue @@ -219,6 +219,10 @@ func SearchAttributeView(keyword string) (ret []*SearchAttributeViewResult) { continue } + if nil == avBlockRels[id] { + continue + } + name, _ := av.GetAttributeViewNameByPath(filepath.Join(avDir, entry.Name())) info, _ := entry.Info() if "" != keyword { @@ -237,23 +241,33 @@ func SearchAttributeView(keyword string) (ret []*SearchAttributeViewResult) { } avs = append(avs, a) } - } if "" == keyword { sort.Slice(avs, func(i, j int) bool { return avs[i].AvUpdated > avs[j].AvUpdated }) } else { - sort.Slice(avs, func(i, j int) bool { return avs[i].Score > avs[j].Score }) + sort.SliceStable(avs, func(i, j int) bool { + if avs[i].Score == avs[j].Score { + return avs[i].AvUpdated > avs[j].AvUpdated + } + return avs[i].Score > avs[j].Score + }) } - if 16 < len(avs) { - avs = avs[:16] + if 12 <= len(avs) { + avs = avs[:12] } var avIDs []string for _, a := range avs { avIDs = append(avIDs, a.AvID) } - blockIDs := treenode.BatchGetMirrorAttrViewBlockIDs(avIDs) + avBlocks := treenode.BatchGetMirrorAttrViewBlocks(avIDs) + var blockIDs []string + for _, avBlock := range avBlocks { + blockIDs = append(blockIDs, avBlock.BlockIDs...) + } + blockIDs = gulu.Str.RemoveDuplicatedElem(blockIDs) + trees := map[string]*parse.Tree{} for _, blockID := range blockIDs { bt := treenode.GetBlockTree(blockID) diff --git a/kernel/treenode/av.go b/kernel/treenode/av.go index d2137d4f1..6fd0e1720 100644 --- a/kernel/treenode/av.go +++ b/kernel/treenode/av.go @@ -26,41 +26,6 @@ import ( "github.com/vmihailenco/msgpack/v5" ) -func BatchGetMirrorAttrViewBlockIDs(avIDs []string) (ret map[string]string) { - av.AttributeViewBlocksLock.Lock() - defer av.AttributeViewBlocksLock.Unlock() - - ret = map[string]string{} - - blocks := filepath.Join(util.DataDir, "storage", "av", "blocks.msgpack") - if !filelock.IsExist(blocks) { - return - } - - data, err := filelock.ReadFile(blocks) - if nil != err { - logging.LogErrorf("read attribute view blocks failed: %s", err) - return - } - - avBlocks := map[string][]string{} - if err = msgpack.Unmarshal(data, &avBlocks); nil != err { - logging.LogErrorf("unmarshal attribute view blocks failed: %s", err) - return - } - - for _, avID := range avIDs { - blockIDs := avBlocks[avID] - for _, blockID := range blockIDs { - if nil != GetBlockTree(blockID) { - ret[avID] = blockID - break - } - } - } - return -} - func GetMirrorAttrViewBlockIDs(avID string) (ret []string) { av.AttributeViewBlocksLock.Lock() defer av.AttributeViewBlocksLock.Unlock() @@ -91,3 +56,49 @@ func GetMirrorAttrViewBlockIDs(avID string) (ret []string) { } return } + +type AvBlock struct { + AvID string + BlockIDs []string +} + +func BatchGetMirrorAttrViewBlocks(avIDs []string) (ret []*AvBlock) { + av.AttributeViewBlocksLock.Lock() + defer av.AttributeViewBlocksLock.Unlock() + + ret = []*AvBlock{} + + blocks := filepath.Join(util.DataDir, "storage", "av", "blocks.msgpack") + if !filelock.IsExist(blocks) { + return + } + + data, err := filelock.ReadFile(blocks) + if nil != err { + logging.LogErrorf("read attribute view blocks failed: %s", err) + return + } + + avBlocks := map[string][]string{} + if err = msgpack.Unmarshal(data, &avBlocks); nil != err { + logging.LogErrorf("unmarshal attribute view blocks failed: %s", err) + return + } + + for _, avID := range avIDs { + var blockIDs []string + for _, blockID := range avBlocks[avID] { + if nil == GetBlockTree(blockID) { + continue + } + + blockIDs = append(blockIDs, blockID) + } + avBlock := &AvBlock{ + AvID: avID, + BlockIDs: blockIDs, + } + ret = append(ret, avBlock) + } + return +}