diff --git a/kernel/model/search.go b/kernel/model/search.go index ce7259c58..8050e6f45 100644 --- a/kernel/model/search.go +++ b/kernel/model/search.go @@ -1279,7 +1279,7 @@ func fullTextSearchByKeyword(query, boxFilter, pathFilter, typeFilter string, or ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen, page, pageSize) return } - return fullTextSearchByUnion(query, boxFilter, pathFilter, typeFilter, orderBy, beforeLen, page, pageSize) + return fullTextSearchByFTSWithRoot(query, boxFilter, pathFilter, typeFilter, orderBy, beforeLen, page, pageSize) } func fullTextSearchByRegexp(exp, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { @@ -1393,7 +1393,7 @@ func fullTextSearchCountByFTS(query, boxFilter, pathFilter, typeFilter string) ( return } -func fullTextSearchByUnion(query, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) { +func fullTextSearchByFTSWithRoot(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" @@ -1417,24 +1417,21 @@ func fullTextSearchByUnion(query, boxFilter, pathFilter, typeFilter, orderBy str query = strings.ReplaceAll(query, "'", "''") query = strings.ReplaceAll(query, "\"", "\"\"") keywords := strings.Split(query, " ") - likeFilter := "(" + var likeFilter string for i, keyword := range keywords { likeFilter += "docContent LIKE '%" + keyword + "%'" if i < len(keywords)-1 { likeFilter += " AND " } } - likeFilter += ")" dMatchStmt := "SELECT root_id, GROUP_CONCAT(content) AS docContent" + " FROM " + table + " WHERE type IN " + typeFilter + boxFilter + pathFilter + ignoreFilter + " GROUP BY root_id HAVING " + likeFilter cteStmt := "WITH docs AS (" + dMatchStmt + "), blocks AS (" + bMatchStmt + ")" - docMatchStmt := "SELECT * FROM " + table + " WHERE id IN (SELECT root_id FROM docs)" - blockMatchStmt := "SELECT * FROM " + table + " WHERE id IN (SELECT id FROM blocks)" - unionStmt := cteStmt + "\nSELECT * FROM (" + blockMatchStmt + " UNION ALL " + docMatchStmt + ")" - countStmt := unionStmt - unionStmt += orderBy + " LIMIT " + strconv.Itoa(pageSize) + " OFFSET " + strconv.Itoa((page-1)*pageSize) - resultBlocks := sql.SelectBlocksRawStmtNoParse(unionStmt, -1) + cteStmt += "\nSELECT * FROM " + table + " WHERE id IN (SELECT id FROM blocks) OR id IN (SELECT root_id FROM docs)" + countStmt := cteStmt + cteStmt += orderBy + " LIMIT " + strconv.Itoa(pageSize) + " OFFSET " + strconv.Itoa((page-1)*pageSize) + resultBlocks := sql.SelectBlocksRawStmtNoParse(cteStmt, -1) // FTS 高亮 projections := "id, parent_id, root_id, hash, box, path, " + @@ -1465,11 +1462,11 @@ func fullTextSearchByUnion(query, boxFilter, pathFilter, typeFilter, orderBy str ret = []*Block{} } - matchedBlockCount, matchedRootCount = fullTextSearchCountByUnion(countStmt) + matchedBlockCount, matchedRootCount = fullTextSearchCountByStmt(countStmt) return } -func fullTextSearchCountByUnion(stmt string) (matchedBlockCount, matchedRootCount int) { +func fullTextSearchCountByStmt(stmt string) (matchedBlockCount, matchedRootCount int) { stmt = "SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM (" + stmt + ")" result, _ := sql.QueryNoLimit(stmt) if 1 > len(result) {