From 60bef349a09d2d75115894958bc1553fdfb3345e Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Thu, 28 Jul 2022 01:14:49 +0800 Subject: [PATCH 1/2] =?UTF-8?q?:art:=20=E6=90=9C=E7=B4=A2=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=E5=8A=A0=E5=85=A5=E5=91=BD=E4=B8=AD=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=20https://github.com/siyuan-note/siyuan/issues/5505?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/api/search.go | 8 ++++-- kernel/model/search.go | 55 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/kernel/api/search.go b/kernel/api/search.go index 1fe8a0315..e66fcc643 100644 --- a/kernel/api/search.go +++ b/kernel/api/search.go @@ -206,6 +206,10 @@ func fullTextSearchBlock(c *gin.Context) { if nil != querySyntaxArg { querySyntax = querySyntaxArg.(bool) } - blocks := model.FullTextSearchBlock(query, box, path, types, querySyntax) - ret.Data = blocks + blocks, matchedBlockCount, matchedRootCount := model.FullTextSearchBlock(query, box, path, types, querySyntax) + ret.Data = map[string]interface{}{ + "blocks": blocks, + "matchedBlockCount": matchedBlockCount, + "matchedRootCount": matchedRootCount, + } } diff --git a/kernel/model/search.go b/kernel/model/search.go index 8bce20e88..5e552adc0 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -188,13 +188,13 @@ func FindReplace(keyword, replacement string, ids []string) (err error) { return } -func FullTextSearchBlock(query, box, path string, types map[string]bool, querySyntax bool) (ret []*Block) { +func FullTextSearchBlock(query, box, path string, types map[string]bool, querySyntax bool) (ret []*Block, matchedBlockCount, matchedRootCount int) { query = strings.TrimSpace(query) if queryStrLower := strings.ToLower(query); strings.Contains(queryStrLower, "select ") && strings.Contains(queryStrLower, " * ") && strings.Contains(queryStrLower, " from ") { - ret = searchBySQL(query, 36) + ret, matchedBlockCount, matchedRootCount = searchBySQL(query, 36) } else { filter := searchFilter(types) - ret = fullTextSearch(query, box, path, filter, 36, querySyntax) + ret, matchedBlockCount, matchedRootCount = fullTextSearch(query, box, path, filter, 36, querySyntax) } return } @@ -232,13 +232,24 @@ func searchFilter(types map[string]bool) string { return s.TypeFilter() } -func searchBySQL(stmt string, beforeLen int) (ret []*Block) { +func searchBySQL(stmt string, beforeLen int) (ret []*Block, matchedBlockCount, matchedRootCount int) { stmt = gulu.Str.RemoveInvisible(stmt) blocks := sql.SelectBlocksRawStmt(stmt, Conf.Search.Limit) ret = fromSQLBlocks(&blocks, "", beforeLen) if 1 > len(ret) { ret = []*Block{} + return } + + stmt = strings.ToLower(stmt) + stmt = strings.ReplaceAll(stmt, "select * ", "select COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` ") + result, _ := sql.Query(stmt) + if 1 > len(ret) { + return + } + + matchedBlockCount = int(result[0]["matches"].(int64)) + matchedRootCount = int(result[0]["docs"].(int64)) return } @@ -246,7 +257,7 @@ func fullTextSearchRefBlock(keyword string, beforeLen int) (ret []*Block) { keyword = gulu.Str.RemoveInvisible(keyword) if util.IsIDPattern(keyword) { - ret = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+keyword+"'", 36) + ret, _, _ = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+keyword+"'", 36) return } @@ -290,10 +301,38 @@ func fullTextSearchRefBlock(keyword string, beforeLen int) (ret []*Block) { return } -func fullTextSearch(query, box, path, filter string, beforeLen int, querySyntax bool) (ret []*Block) { +func fullTextSearchCount(query, box, path, filter string) (matchedBlockCount, matchedRootCount int) { query = gulu.Str.RemoveInvisible(query) if util.IsIDPattern(query) { - ret = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen) + ret, _ := sql.Query("SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `blocks` WHERE `id` = '" + query + "'") + if 1 > len(ret) { + return + } + matchedBlockCount = int(ret[0]["matches"].(int64)) + matchedRootCount = int(ret[0]["docs"].(int64)) + return + } + + stmt := "SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `blocks_fts` WHERE `blocks_fts` MATCH '" + columnFilter() + ":(" + query + ")' AND type IN " + filter + if "" != box { + stmt += " AND box = '" + box + "'" + } + if "" != path { + stmt += " AND path LIKE '" + path + "%'" + } + result, _ := sql.Query(stmt) + if 1 > len(result) { + return + } + matchedBlockCount = int(result[0]["matches"].(int64)) + matchedRootCount = int(result[0]["docs"].(int64)) + return +} + +func fullTextSearch(query, box, path, filter string, beforeLen int, querySyntax bool) (ret []*Block, matchedBlockCount, matchedRootCount int) { + query = gulu.Str.RemoveInvisible(query) + if util.IsIDPattern(query) { + ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen) return } @@ -326,6 +365,8 @@ func fullTextSearch(query, box, path, filter string, beforeLen int, querySyntax if 1 > len(ret) { ret = []*Block{} } + + matchedBlockCount, matchedRootCount = fullTextSearchCount(query, box, path, filter) return } From 23c4d2ab61ed20c7ba3a363b1e0d7128692167f1 Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Thu, 28 Jul 2022 01:15:13 +0800 Subject: [PATCH 2/2] =?UTF-8?q?:recycle:=20SQL=20=E5=85=B3=E9=94=AE?= =?UTF-8?q?=E5=AD=97=E4=BD=BF=E7=94=A8=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/sql/stat.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sql/stat.go b/kernel/sql/stat.go index 05bedad7d..8e0f2f45e 100644 --- a/kernel/sql/stat.go +++ b/kernel/sql/stat.go @@ -94,7 +94,7 @@ func getStat(key string) (ret string) { } func CountAllDoc() (ret int) { - sqlStmt := "SELECT count(*) FROM blocks WHERE type = 'd'" + sqlStmt := "SELECT COUNT(*) FROM blocks WHERE type = 'd'" row := queryRow(sqlStmt) row.Scan(&ret) return