diff --git a/kernel/api/search.go b/kernel/api/search.go index f99868a7b..2db996a5b 100644 --- a/kernel/api/search.go +++ b/kernel/api/search.go @@ -35,7 +35,7 @@ func findReplace(c *gin.Context) { return } - _, _, paths, boxes, types, method, orderBy, groupBy := parseSearchArgs(arg) + _, _, _, paths, boxes, types, method, orderBy, groupBy := parseSearchArgs(arg) k := arg["k"].(string) r := arg["r"].(string) @@ -215,8 +215,8 @@ func fullTextSearchBlock(c *gin.Context) { return } - page, query, paths, boxes, types, method, orderBy, groupBy := parseSearchArgs(arg) - blocks, matchedBlockCount, matchedRootCount, pageCount := model.FullTextSearchBlock(query, boxes, paths, types, method, orderBy, groupBy, page) + page, pageSize, query, paths, boxes, types, method, orderBy, groupBy := parseSearchArgs(arg) + blocks, matchedBlockCount, matchedRootCount, pageCount := model.FullTextSearchBlock(query, boxes, paths, types, method, orderBy, groupBy, page, pageSize) ret.Data = map[string]interface{}{ "blocks": blocks, "matchedBlockCount": matchedBlockCount, @@ -225,7 +225,7 @@ func fullTextSearchBlock(c *gin.Context) { } } -func parseSearchArgs(arg map[string]interface{}) (page int, query string, paths, boxes []string, types map[string]bool, method, orderBy, groupBy int) { +func parseSearchArgs(arg map[string]interface{}) (page, pageSize int, query string, paths, boxes []string, types map[string]bool, method, orderBy, groupBy int) { page = 1 if nil != arg["page"] { page = int(arg["page"].(float64)) @@ -234,6 +234,14 @@ func parseSearchArgs(arg map[string]interface{}) (page int, query string, paths, page = 1 } + pageSize = 32 + if nil != arg["pageSize"] { + pageSize = int(arg["pageSize"].(float64)) + } + if 0 >= pageSize { + pageSize = 32 + } + queryArg := arg["query"] if nil != queryArg { query = queryArg.(string) diff --git a/kernel/model/search.go b/kernel/model/search.go index b49e0500b..c3ab10748 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -20,6 +20,7 @@ import ( "bytes" "errors" "fmt" + "math" "os" "path" "path/filepath" @@ -234,7 +235,7 @@ func FindReplace(keyword, replacement string, ids []string, paths, boxes []strin if 1 > len(ids) { // `Replace All` is no longer affected by pagination https://github.com/siyuan-note/siyuan/issues/8265 - blocks, _, _, _ := FullTextSearchBlock(keyword, boxes, paths, types, method, orderBy, groupBy, 1) + blocks, _, _, _ := FullTextSearchBlock(keyword, boxes, paths, types, method, orderBy, groupBy, 1, math.MaxInt) for _, block := range blocks { ids = append(ids, block.ID) } @@ -277,7 +278,7 @@ func FindReplace(keyword, replacement string, ids []string, paths, boxes []strin } indexHistoryDir(filepath.Base(historyDir), util.NewLute()) - for _, id := range ids { + for i, id := range ids { bt := treenode.GetBlockTree(id) if nil == bt { continue @@ -387,6 +388,8 @@ func FindReplace(keyword, replacement string, ids []string, paths, boxes []strin if err = writeJSONQueue(tree); nil != err { return } + + util.PushEndlessProgress(fmt.Sprintf(Conf.Language(70), fmt.Sprintf("%d/%d", i, len(ids)))) } for _, renameRoot := range renameRoots { @@ -404,14 +407,12 @@ func FindReplace(keyword, replacement string, ids []string, paths, boxes []strin return } -const pageSize = 32 - // FullTextSearchBlock 搜索内容块。 // // method:0:关键字,1:查询语法,2:SQL,3:正则表达式 // orderBy: 0:按块类型(默认),1:按创建时间升序,2:按创建时间降序,3:按更新时间升序,4:按更新时间降序,5:按内容顺序(仅在按文档分组时),6:按相关度升序,7:按相关度降序 // groupBy:0:不分组,1:按文档分组 -func FullTextSearchBlock(query string, boxes, paths []string, types map[string]bool, method, orderBy, groupBy, page int) (ret []*Block, matchedBlockCount, matchedRootCount, pageCount int) { +func FullTextSearchBlock(query string, boxes, paths []string, types map[string]bool, method, orderBy, groupBy, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount, pageCount int) { query = strings.TrimSpace(query) beforeLen := 36 var blocks []*Block @@ -421,19 +422,19 @@ func FullTextSearchBlock(query string, boxes, paths []string, types map[string]b filter := buildTypeFilter(types) boxFilter := buildBoxesFilter(boxes) pathFilter := buildPathsFilter(paths) - blocks, matchedBlockCount, matchedRootCount = fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, filter, orderByClause, beforeLen, page) + blocks, matchedBlockCount, matchedRootCount = fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, filter, orderByClause, beforeLen, page, pageSize) case 2: // SQL - blocks, matchedBlockCount, matchedRootCount = searchBySQL(query, beforeLen, page) + blocks, matchedBlockCount, matchedRootCount = searchBySQL(query, beforeLen, page, pageSize) case 3: // 正则表达式 typeFilter := buildTypeFilter(types) boxFilter := buildBoxesFilter(boxes) pathFilter := buildPathsFilter(paths) - blocks, matchedBlockCount, matchedRootCount = fullTextSearchByRegexp(query, boxFilter, pathFilter, typeFilter, orderByClause, beforeLen, page) + blocks, matchedBlockCount, matchedRootCount = fullTextSearchByRegexp(query, boxFilter, pathFilter, typeFilter, orderByClause, beforeLen, page, pageSize) default: // 关键字 filter := buildTypeFilter(types) boxFilter := buildBoxesFilter(boxes) pathFilter := buildPathsFilter(paths) - blocks, matchedBlockCount, matchedRootCount = fullTextSearchByKeyword(query, boxFilter, pathFilter, filter, orderByClause, beforeLen, page) + blocks, matchedBlockCount, matchedRootCount = fullTextSearchByKeyword(query, boxFilter, pathFilter, filter, orderByClause, beforeLen, page, pageSize) } pageCount = (matchedBlockCount + pageSize - 1) / pageSize @@ -615,7 +616,7 @@ func buildTypeFilter(types map[string]bool) string { return s.TypeFilter() } -func searchBySQL(stmt string, beforeLen, page int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func searchBySQL(stmt string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { stmt = gulu.Str.RemoveInvisible(stmt) stmt = strings.TrimSpace(stmt) blocks := sql.SelectBlocksRawStmt(stmt, page, pageSize) @@ -663,7 +664,7 @@ func fullTextSearchRefBlock(keyword string, beforeLen int, onlyDoc bool) (ret [] keyword = gulu.Str.RemoveInvisible(keyword) if ast.IsNodeIDPattern(keyword) { - ret, _, _ = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+keyword+"'", 36, 1) + ret, _, _ = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+keyword+"'", 36, 1, 32) return } @@ -712,26 +713,26 @@ func fullTextSearchRefBlock(keyword string, beforeLen int, onlyDoc bool) (ret [] return } -func fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { query = gulu.Str.RemoveInvisible(query) if ast.IsNodeIDPattern(query) { - ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen, page) + ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen, page, pageSize) return } - return fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy, beforeLen, page) + return fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy, beforeLen, page, pageSize) } -func fullTextSearchByKeyword(query, boxFilter, pathFilter, typeFilter string, orderBy string, beforeLen, page int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func fullTextSearchByKeyword(query, boxFilter, pathFilter, typeFilter string, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { query = gulu.Str.RemoveInvisible(query) if ast.IsNodeIDPattern(query) { - ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen, page) + ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen, page, pageSize) return } query = stringQuery(query) - return fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy, beforeLen, page) + return fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy, beforeLen, page, pageSize) } -func fullTextSearchByRegexp(exp, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func fullTextSearchByRegexp(exp, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { exp = gulu.Str.RemoveInvisible(exp) fieldFilter := fieldRegexp(exp) @@ -762,7 +763,7 @@ func fullTextSearchCountByRegexp(exp, boxFilter, pathFilter, typeFilter string) return } -func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { table := "blocks_fts" // 大小写敏感 if !Conf.Search.CaseSensitive { table = "blocks_fts_case_insensitive"