Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Vanessa 2023-06-29 18:56:57 +08:00
commit 7ea6f08c21
7 changed files with 82 additions and 45 deletions

View file

@ -1171,6 +1171,8 @@
"202": "Cleaning data repo...",
"203": "The data repo is purged, [%d] snapshots and [%d] data objects have been deleted, and a total of [%s] disk space has been released",
"204": "The doc in the user guide does not support sharing to the community",
"205": "The plugin is not supported in the current environment"
"205": "The plugin is not supported in the current environment",
"206": "Executing content replacement [%d/%d]",
"207": "Executing path replacement [%d/%d]"
}
}

View file

@ -1171,6 +1171,8 @@
"202": "Limpiando repositorio de datos...",
"203": "El repositorio de datos se purgó, [%d] instantáneas y [%d] objetos de datos se eliminaron y se liberó un total de [%s] espacio en disco",
"204": "La documentación en la guía del usuario no permite compartir con la comunidad",
"205": "El complemento no es compatible con el entorno actual"
"205": "El complemento no es compatible con el entorno actual",
"206": "Ejecutando reemplazo de contenido [%d/%d]",
"207": "Ejecutando reemplazo de ruta [%d/%d]"
}
}

View file

@ -1171,6 +1171,8 @@
"202": "Nettoyage du référentiel de données...",
"203": "Le référentiel de données est purgé, [%d] instantanés et [%d] objets de données ont été supprimés, et un total de [%s] espace disque a été libéré",
"204": "La documentation du guide de l'utilisateur ne prend pas en charge le partage avec la communauté",
"205": "Le plugin n'est pas pris en charge dans l'environnement actuel"
"205": "Le plugin n'est pas pris en charge dans l'environnement actuel",
"206": "Exécution du remplacement de contenu [%d/%d]",
"207": "Exécution du remplacement de chemin [%d/%d]"
}
}

View file

@ -1171,6 +1171,8 @@
"202": "正在清理數據倉庫...",
"203": "數據倉庫清理完畢,已刪除 [%d] 個快照和 [%d] 個數據對象,共釋放 [%s] 磁盤空間",
"204": "用戶指南中的文檔不支持分享到社區",
"205": "該插件不支持在當前環境下使用"
"205": "該插件不支持在當前環境下使用",
"206": "正在執行內容替換 [%d/%d]",
"207": "正在執行路徑替換 [%d/%d]"
}
}

View file

@ -1173,6 +1173,8 @@
"202": "正在清理数据仓库...",
"203": "数据仓库清理完毕,已删除 [%d] 个快照和 [%d] 个数据对象,共释放 [%s] 磁盘空间",
"204": "用户指南中的文档不支持分享到社区",
"205": "该插件不支持在当前环境下使用"
"205": "该插件不支持在当前环境下使用",
"206": "正在执行内容替换 [%d/%d]",
"207": "正在执行路径替换 [%d/%d]"
}
}

View file

@ -35,19 +35,16 @@ func findReplace(c *gin.Context) {
return
}
_, _, _, paths, boxes, types, method, orderBy, groupBy := parseSearchArgs(arg)
k := arg["k"].(string)
r := arg["r"].(string)
methodArg := arg["method"]
var method int // 0文本1查询语法2SQL3正则表达式
if nil != methodArg {
method = int(methodArg.(float64))
}
idsArg := arg["ids"].([]interface{})
var ids []string
for _, id := range idsArg {
ids = append(ids, id.(string))
}
err := model.FindReplace(k, r, ids, method)
err := model.FindReplace(k, r, ids, paths, boxes, types, method, orderBy, groupBy)
if nil != err {
ret.Code = -1
ret.Msg = err.Error()
@ -218,7 +215,18 @@ func fullTextSearchBlock(c *gin.Context) {
return
}
page := 1
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,
"matchedRootCount": matchedRootCount,
"pageCount": pageCount,
}
}
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))
}
@ -226,9 +234,20 @@ func fullTextSearchBlock(c *gin.Context) {
page = 1
}
query := arg["query"].(string)
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)
}
pathsArg := arg["paths"]
var paths, boxes []string
if nil != pathsArg {
for _, p := range pathsArg.([]interface{}) {
path := p.(string)
@ -244,7 +263,7 @@ func fullTextSearchBlock(c *gin.Context) {
paths = gulu.Str.RemoveDuplicatedElem(paths)
boxes = gulu.Str.RemoveDuplicatedElem(boxes)
}
var types map[string]bool
if nil != arg["types"] {
typesArg := arg["types"].(map[string]interface{})
types = map[string]bool{}
@ -252,26 +271,23 @@ func fullTextSearchBlock(c *gin.Context) {
types[t] = b.(bool)
}
}
// method0关键字1查询语法2SQL3正则表达式
methodArg := arg["method"]
var method int // 0关键字1查询语法2SQL3正则表达式
if nil != methodArg {
method = int(methodArg.(float64))
}
// orderBy0按块类型默认1按创建时间升序2按创建时间降序3按更新时间升序4按更新时间降序5按内容顺序仅在按文档分组时6按相关度升序7按相关度降序
orderByArg := arg["orderBy"]
var orderBy int // 0按块类型默认1按创建时间升序2按创建时间降序3按更新时间升序4按更新时间降序5按内容顺序仅在按文档分组时6按相关度升序7按相关度降序
if nil != orderByArg {
orderBy = int(orderByArg.(float64))
}
// groupBy 0不分组1按文档分组
groupByArg := arg["groupBy"]
var groupBy int // 0不分组1按文档分组
if nil != groupByArg {
groupBy = int(groupByArg.(float64))
}
blocks, matchedBlockCount, matchedRootCount, pageCount := model.FullTextSearchBlock(query, boxes, paths, types, method, orderBy, groupBy, page)
ret.Data = map[string]interface{}{
"blocks": blocks,
"matchedBlockCount": matchedBlockCount,
"matchedRootCount": matchedRootCount,
"pageCount": pageCount,
}
return
}

View file

@ -20,6 +20,7 @@ import (
"bytes"
"errors"
"fmt"
"math"
"os"
"path"
"path/filepath"
@ -207,7 +208,7 @@ func SearchRefBlock(id, rootID, keyword string, beforeLen int, isSquareBrackets
return
}
func FindReplace(keyword, replacement string, ids []string, method int) (err error) {
func FindReplace(keyword, replacement string, ids []string, paths, boxes []string, types map[string]bool, method, orderBy, groupBy int) (err error) {
// method0文本1查询语法2SQL3正则表达式
if 1 == method || 2 == method {
err = errors.New(Conf.Language(132))
@ -232,6 +233,14 @@ func FindReplace(keyword, replacement string, ids []string, method int) (err err
return
}
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, math.MaxInt)
for _, block := range blocks {
ids = append(ids, block.ID)
}
}
for _, id := range ids {
bt := treenode.GetBlockTree(id)
if nil == bt {
@ -269,7 +278,7 @@ func FindReplace(keyword, replacement string, ids []string, method int) (err err
}
indexHistoryDir(filepath.Base(historyDir), util.NewLute())
for _, id := range ids {
for i, id := range ids {
bt := treenode.GetBlockTree(id)
if nil == bt {
continue
@ -379,11 +388,15 @@ func FindReplace(keyword, replacement string, ids []string, method int) (err err
if err = writeJSONQueue(tree); nil != err {
return
}
util.PushEndlessProgress(fmt.Sprintf(Conf.Language(206), i+1, len(ids)))
}
for _, renameRoot := range renameRoots {
for i, renameRoot := range renameRoots {
newTitle := renameRootTitles[renameRoot.ID]
RenameDoc(renameRoot.Box, renameRoot.Path, newTitle)
util.PushEndlessProgress(fmt.Sprintf(Conf.Language(207), i+1, len(ids)))
}
WaitForWritingFiles()
@ -396,14 +409,12 @@ func FindReplace(keyword, replacement string, ids []string, method int) (err err
return
}
const pageSize = 32
// FullTextSearchBlock 搜索内容块。
//
// method0关键字1查询语法2SQL3正则表达式
// orderBy: 0按块类型默认1按创建时间升序2按创建时间降序3按更新时间升序4按更新时间降序5按内容顺序仅在按文档分组时6按相关度升序7按相关度降序
// groupBy0不分组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
@ -413,19 +424,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
@ -607,7 +618,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)
@ -655,7 +666,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
}
@ -704,26 +715,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)
@ -754,7 +765,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"