diff --git a/kernel/conf/search.go b/kernel/conf/search.go index 80275d1b7..eace0a039 100644 --- a/kernel/conf/search.go +++ b/kernel/conf/search.go @@ -36,6 +36,7 @@ type Search struct { SuperBlock bool `json:"superBlock"` Paragraph bool `json:"paragraph"` HTMLBlock bool `json:"htmlBlock"` + EmbedBlock bool `json:"embedBlock"` Limit int `json:"limit"` CaseSensitive bool `json:"caseSensitive"` @@ -71,6 +72,7 @@ func NewSearch() *Search { SuperBlock: true, Paragraph: true, HTMLBlock: true, + EmbedBlock: false, Limit: 64, CaseSensitive: true, @@ -180,6 +182,12 @@ func (s *Search) TypeFilter() string { buf.WriteByte('\'') buf.WriteString(",") } + if s.EmbedBlock { + buf.WriteByte('\'') + buf.WriteString(treenode.TypeAbbr(ast.NodeBlockQueryEmbed.String())) + buf.WriteByte('\'') + buf.WriteString(",") + } // 无法搜索到 iframe 块、视频块和音频块 https://github.com/siyuan-note/siyuan/issues/3604 buf.WriteString("'iframe','query_embed','video','audio',") // 挂件块支持内置属性搜索 https://github.com/siyuan-note/siyuan/issues/4497 diff --git a/kernel/main.go b/kernel/main.go index caf2dd1c7..d0f6dcc12 100644 --- a/kernel/main.go +++ b/kernel/main.go @@ -56,6 +56,7 @@ func main() { go treenode.AutoFlushBlockTree() go cache.LoadAssets() go model.AutoFixIndex() + go model.AutoIndexEmbedBlock() go model.AutoOCRAssets() go model.AutoFlushAssetsTexts() go model.HookDesktopUIProc() diff --git a/kernel/mobile/kernel.go b/kernel/mobile/kernel.go index c043809dc..58c3d9019 100644 --- a/kernel/mobile/kernel.go +++ b/kernel/mobile/kernel.go @@ -70,6 +70,7 @@ func StartKernel(container, appDir, workspaceBaseDir, timezoneID, localIPs, lang go treenode.AutoFlushBlockTree() go cache.LoadAssets() go model.AutoFixIndex() + go model.AutoIndexEmbedBlock() go model.AutoOCRAssets() go model.AutoFlushAssetsTexts() }() diff --git a/kernel/model/ocr.go b/kernel/model/ocr.go index 96c493c8b..fa971bc93 100644 --- a/kernel/model/ocr.go +++ b/kernel/model/ocr.go @@ -57,7 +57,7 @@ func autoOCRAssets() { waitGroup.Add(1) p.Invoke(assetAbsPath) - if 63 <= i { // 一次最多处理 64 张图片,防止卡顿 + if 63 <= i { // 一次任务中最多处理 64 张图片,防止卡顿 break } } diff --git a/kernel/model/search.go b/kernel/model/search.go index d6f140836..0ba4dad2a 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -58,6 +58,11 @@ func searchEmbedBlock(embedBlockID, stmt string, excludeIDs []string, headingMod sqlBlocks := sql.SelectBlocksRawStmtNoParse(stmt, Conf.Search.Limit) var tmp []*sql.Block for _, b := range sqlBlocks { + if "query_embed" == b.Type { // 嵌入块不再嵌入 + // 嵌入块支持搜索 https://github.com/siyuan-note/siyuan/issues/7112 + // 这里会导致上面的 limit 限制不准确,导致结果变少,暂时没有解决方案,只能靠用户自己调整 SQL,加上 type != 'query_embed' 的条件 + continue + } if !gulu.Str.Contains(b.ID, excludeIDs) { tmp = append(tmp, b) } @@ -494,6 +499,7 @@ func buildTypeFilter(types map[string]bool) string { s.SuperBlock = types["superBlock"] s.Paragraph = types["paragraph"] s.HTMLBlock = types["htmlBlock"] + s.EmbedBlock = types["embedBlock"] } else { s.Document = Conf.Search.Document s.Heading = Conf.Search.Heading @@ -506,6 +512,7 @@ func buildTypeFilter(types map[string]bool) string { s.SuperBlock = Conf.Search.SuperBlock s.Paragraph = Conf.Search.Paragraph s.HTMLBlock = Conf.Search.HTMLBlock + s.EmbedBlock = Conf.Search.EmbedBlock } return s.TypeFilter() } diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index cda7666c9..b3c19d9a7 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -1216,6 +1216,31 @@ func updateRefText(refNode *ast.Node, changedDefNodes map[string]*ast.Node) (cha return } +// AutoIndexEmbedBlock 嵌入块支持搜索 https://github.com/siyuan-note/siyuan/issues/7112 +func AutoIndexEmbedBlock() { + for { + task.AppendTask(task.DatabaseIndexEmbedBlock, autoIndexEmbedBlock) + time.Sleep(30 * time.Second) + } +} + +func autoIndexEmbedBlock() { + embedBlocks := sql.QueryEmptyContentEmbedBlocks() + for i, embedBlock := range embedBlocks { + stmt := strings.TrimPrefix(embedBlock.Markdown, "{{") + stmt = strings.TrimSuffix(stmt, "}}") + blocks := sql.SelectBlocksRawStmtNoParse(stmt, 102400) + for _, block := range blocks { + embedBlock.Content = block.Content + sql.UpdateBlockContent(embedBlock) + } + + if 63 <= i { // 一次任务中最多处理 64 个嵌入块,防止卡顿 + break + } + } +} + // AutoFixIndex 自动校验数据库索引 https://github.com/siyuan-note/siyuan/issues/7016 func AutoFixIndex() { for { @@ -1229,13 +1254,6 @@ var autoFixLock = sync.Mutex{} func autoFixIndex() { defer logging.Recover() - if util.IsMutexLocked(&autoFixLock) { - return - } - - autoFixLock.Lock() - defer autoFixLock.Unlock() - // 根据文件系统补全块树 boxes := Conf.GetOpenedBoxes() for _, box := range boxes { diff --git a/kernel/sql/block.go b/kernel/sql/block.go index 6a39bd264..d88b888e2 100644 --- a/kernel/sql/block.go +++ b/kernel/sql/block.go @@ -55,9 +55,11 @@ func updateRootContent(tx *sql.Tx, content, updated, id string) { if err := execStmtTx(tx, stmt, content, content, updated, id); nil != err { return } - stmt = "UPDATE blocks_fts_case_insensitive SET content = ?, fcontent = ?, updated = ? WHERE id = ?" - if err := execStmtTx(tx, stmt, content, content, updated, id); nil != err { - return + if !caseSensitive { + stmt = "UPDATE blocks_fts_case_insensitive SET content = ?, fcontent = ?, updated = ? WHERE id = ?" + if err := execStmtTx(tx, stmt, content, content, updated, id); nil != err { + return + } } removeBlockCache(id) cache.RemoveBlockIAL(id) @@ -66,3 +68,30 @@ func updateRootContent(tx *sql.Tx, content, updated, id string) { func InsertBlock(tx *sql.Tx, block *Block, context map[string]interface{}) (err error) { return insertBlocks(tx, []*Block{block}, context) } + +func UpdateBlockContent(block *Block) { + tx, err := BeginTx() + if nil != err { + return + } + + stmt := "UPDATE blocks SET content = ? WHERE id = ?" + if err = execStmtTx(tx, stmt, block.Content, block.ID); nil != err { + tx.Rollback() + return + } + stmt = "UPDATE blocks_fts SET content = ? WHERE id = ?" + if err = execStmtTx(tx, stmt, block.Content, block.ID); nil != err { + tx.Rollback() + return + } + if !caseSensitive { + stmt = "UPDATE blocks_fts_case_insensitive SET content = ? WHERE id = ?" + if err = execStmtTx(tx, stmt, block.Content, block.ID); nil != err { + tx.Rollback() + return + } + } + tx.Commit() + putBlockCache(block) +} diff --git a/kernel/sql/block_query.go b/kernel/sql/block_query.go index 71b5bd8ac..53892b9d6 100644 --- a/kernel/sql/block_query.go +++ b/kernel/sql/block_query.go @@ -31,6 +31,22 @@ import ( "github.com/siyuan-note/siyuan/kernel/util" ) +func QueryEmptyContentEmbedBlocks() (ret []*Block) { + stmt := "SELECT * FROM blocks WHERE type = 'query_embed' AND content = ''" + rows, err := query(stmt) + if nil != err { + logging.LogErrorf("sql query [%s] failed: %s", stmt, err) + return + } + defer rows.Close() + for rows.Next() { + if block := scanBlockRows(rows); nil != block { + ret = append(ret, block) + } + } + return +} + func queryBlockHashes(rootID string) (ret map[string]string) { stmt := "SELECT id, hash FROM blocks WHERE root_id = ?" rows, err := query(stmt, rootID)