Browse Source

:art: Return document blocks when the keyword search hits different block content https://github.com/siyuan-note/siyuan/issues/10584

Daniel 8 months ago
parent
commit
6021603966
2 changed files with 43 additions and 43 deletions
  1. 13 43
      kernel/model/search.go
  2. 30 0
      kernel/sql/block_query.go

+ 13 - 43
kernel/model/search.go

@@ -1290,6 +1290,10 @@ func fullTextSearchByKeyword(query, boxFilter, pathFilter, typeFilter, ignoreFil
 		ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen, page, pageSize)
 		ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen, page, pageSize)
 		return
 		return
 	}
 	}
+
+	if 2 > len(strings.Split(query, " ")) {
+		return fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy, beforeLen, page, pageSize)
+	}
 	return fullTextSearchByFTSWithRoot(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy, beforeLen, page, pageSize)
 	return fullTextSearchByFTSWithRoot(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy, beforeLen, page, pageSize)
 }
 }
 
 
@@ -1324,6 +1328,7 @@ func fullTextSearchCountByRegexp(exp, boxFilter, pathFilter, typeFilter, ignoreF
 }
 }
 
 
 func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) {
 func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderBy string, beforeLen, page, pageSize int) (ret []*Block, matchedBlockCount, matchedRootCount int) {
+	start := time.Now()
 	query = stringQuery(query)
 	query = stringQuery(query)
 	table := "blocks_fts" // 大小写敏感
 	table := "blocks_fts" // 大小写敏感
 	if !Conf.Search.CaseSensitive {
 	if !Conf.Search.CaseSensitive {
@@ -1349,20 +1354,11 @@ func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter,
 	}
 	}
 
 
 	matchedBlockCount, matchedRootCount = fullTextSearchCountByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter)
 	matchedBlockCount, matchedRootCount = fullTextSearchCountByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter)
+	logging.LogInfof("time cost [fts]: %v", time.Since(start))
 	return
 	return
 }
 }
 
 
 func fullTextSearchCountByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter string) (matchedBlockCount, matchedRootCount int) {
 func fullTextSearchCountByFTS(query, boxFilter, pathFilter, typeFilter, ignoreFilter string) (matchedBlockCount, matchedRootCount int) {
-	if ast.IsNodeIDPattern(query) {
-		ret, _ := sql.QueryNoLimit("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
-	}
-
 	table := "blocks_fts" // 大小写敏感
 	table := "blocks_fts" // 大小写敏感
 	if !Conf.Search.CaseSensitive {
 	if !Conf.Search.CaseSensitive {
 		table = "blocks_fts_case_insensitive"
 		table = "blocks_fts_case_insensitive"
@@ -1403,43 +1399,17 @@ func fullTextSearchByFTSWithRoot(query, boxFilter, pathFilter, typeFilter, ignor
 		" GROUP BY root_id HAVING " + likeFilter + "ORDER BY " + orderByLike + " DESC, MAX(updated) DESC"
 		" GROUP BY root_id HAVING " + likeFilter + "ORDER BY " + orderByLike + " DESC, MAX(updated) DESC"
 	cteStmt := "WITH docBlocks AS (" + dMatchStmt + ")"
 	cteStmt := "WITH docBlocks AS (" + dMatchStmt + ")"
 	likeFilter = strings.ReplaceAll(likeFilter, "GROUP_CONCAT("+contentField+")", "concatContent")
 	likeFilter = strings.ReplaceAll(likeFilter, "GROUP_CONCAT("+contentField+")", "concatContent")
+	limit := " LIMIT " + strconv.Itoa(pageSize) + " OFFSET " + strconv.Itoa((page-1)*pageSize)
 	selectStmt := cteStmt + "\nSELECT *, " +
 	selectStmt := cteStmt + "\nSELECT *, " +
 		"(" + contentField + ") AS concatContent, " +
 		"(" + contentField + ") AS concatContent, " +
 		"(SELECT COUNT(root_id) FROM docBlocks) AS docs, " +
 		"(SELECT COUNT(root_id) FROM docBlocks) AS docs, " +
 		"(CASE WHEN (root_id IN (SELECT root_id FROM docBlocks) AND (" + strings.ReplaceAll(likeFilter, "concatContent", contentField) + ")) THEN 1 ELSE 0 END) AS blockSort" +
 		"(CASE WHEN (root_id IN (SELECT root_id FROM docBlocks) AND (" + strings.ReplaceAll(likeFilter, "concatContent", contentField) + ")) THEN 1 ELSE 0 END) AS blockSort" +
 		" FROM blocks WHERE type IN " + typeFilter + boxFilter + pathFilter + ignoreFilter +
 		" FROM blocks WHERE type IN " + typeFilter + boxFilter + pathFilter + ignoreFilter +
-		" AND (id IN (SELECT root_id FROM docBlocks) OR" +
-		"  (root_id IN (SELECT root_id FROM docBlocks) AND (" + likeFilter + ")))"
-	selectStmt += " " + strings.Replace(orderBy, "END ASC, ", "END ASC, blockSort DESC, ", 1) +
-		" LIMIT " + strconv.Itoa(pageSize) + " OFFSET " + strconv.Itoa((page-1)*pageSize)
-	result, _ := sql.Query(selectStmt, -1)
-	var resultBlocks []*sql.Block
-	for _, row := range result {
-		b := &sql.Block{
-			ID:       row["id"].(string),
-			ParentID: row["parent_id"].(string),
-			RootID:   row["root_id"].(string),
-			Hash:     row["hash"].(string),
-			Box:      row["box"].(string),
-			Path:     row["path"].(string),
-			HPath:    row["hpath"].(string),
-			Name:     row["name"].(string),
-			Alias:    row["alias"].(string),
-			Memo:     row["memo"].(string),
-			Tag:      row["tag"].(string),
-			Content:  row["content"].(string),
-			FContent: row["fcontent"].(string),
-			Markdown: row["markdown"].(string),
-			Length:   int(row["length"].(int64)),
-			Type:     row["type"].(string),
-			SubType:  row["subtype"].(string),
-			IAL:      row["ial"].(string),
-			Sort:     int(row["sort"].(int64)),
-			Created:  row["created"].(string),
-			Updated:  row["updated"].(string),
-		}
-		resultBlocks = append(resultBlocks, b)
-	}
+		" AND (id IN (SELECT root_id FROM docBlocks " + limit + ") OR" +
+		"  (root_id IN (SELECT root_id FROM docBlocks" + limit + ") AND (" + likeFilter + ")))"
+	selectStmt += " " + strings.Replace(orderBy, "END ASC, ", "END ASC, blockSort DESC, ", 1)
+	result, _ := sql.QueryNoLimit(selectStmt)
+	resultBlocks := sql.ToBlocks(result)
 	if 0 < len(resultBlocks) {
 	if 0 < len(resultBlocks) {
 		matchedRootCount = int(result[0]["docs"].(int64))
 		matchedRootCount = int(result[0]["docs"].(int64))
 		matchedBlockCount = matchedRootCount
 		matchedBlockCount = matchedRootCount
@@ -1452,7 +1422,7 @@ func fullTextSearchByFTSWithRoot(query, boxFilter, pathFilter, typeFilter, ignor
 		ret = []*Block{}
 		ret = []*Block{}
 	}
 	}
 
 
-	logging.LogInfof("time cost [search]: %v", time.Since(start))
+	logging.LogInfof("time cost [like]: %v", time.Since(start))
 	return
 	return
 }
 }
 
 

+ 30 - 0
kernel/sql/block_query.go

@@ -457,6 +457,36 @@ func Query(stmt string, limit int) (ret []map[string]interface{}, err error) {
 	return
 	return
 }
 }
 
 
+func ToBlocks(result []map[string]interface{}) (ret []*Block) {
+	for _, row := range result {
+		b := &Block{
+			ID:       row["id"].(string),
+			ParentID: row["parent_id"].(string),
+			RootID:   row["root_id"].(string),
+			Hash:     row["hash"].(string),
+			Box:      row["box"].(string),
+			Path:     row["path"].(string),
+			HPath:    row["hpath"].(string),
+			Name:     row["name"].(string),
+			Alias:    row["alias"].(string),
+			Memo:     row["memo"].(string),
+			Tag:      row["tag"].(string),
+			Content:  row["content"].(string),
+			FContent: row["fcontent"].(string),
+			Markdown: row["markdown"].(string),
+			Length:   int(row["length"].(int64)),
+			Type:     row["type"].(string),
+			SubType:  row["subtype"].(string),
+			IAL:      row["ial"].(string),
+			Sort:     int(row["sort"].(int64)),
+			Created:  row["created"].(string),
+			Updated:  row["updated"].(string),
+		}
+		ret = append(ret, b)
+	}
+	return
+}
+
 func getLimitClause(parsedStmt sqlparser.Statement, limit int) (ret *sqlparser.Limit) {
 func getLimitClause(parsedStmt sqlparser.Statement, limit int) (ret *sqlparser.Limit) {
 	switch parsedStmt.(type) {
 	switch parsedStmt.(type) {
 	case *sqlparser.Select:
 	case *sqlparser.Select: