fix: search chunk cannot get result (#17328)

This commit is contained in:
Haruko386
2026-07-24 11:01:30 +08:00
committed by GitHub
parent 297890b437
commit 74218bdd6a
2 changed files with 130 additions and 3 deletions

View File

@@ -839,15 +839,44 @@ func (s *ChunkService) List(req *service.ListChunksRequest, userID string) (*ser
page := common.CoalesceInt(req.Page, 1)
size := common.CoalesceInt(req.Size, 30)
keywords := req.Keywords
keywords := strings.TrimSpace(req.Keywords)
matchExprs := make([]interface{}, 0, 1)
if keywords != "" {
matchExprs = append(matchExprs, &types.MatchTextExpr{
MatchingText: keywords,
TopN: size,
})
}
// Build search request - same as retrieval test but filtered by doc_id
searchReq := &types.SearchRequest{
IndexNames: []string{indexName},
MatchExprs: []interface{}{keywords},
MatchExprs: matchExprs,
KbIDs: kbIDs,
Offset: (page - 1) * size,
Limit: size,
SelectFields: []string{
"id",
"content_with_weight",
"img_id",
"position_int",
"docnm",
"important_keywords",
"questions",
"entities_kwd",
"entity_kwd",
"entity_type_kwd",
"from_entity_kwd",
"name_kwd",
"raptor_kwd",
"removed_kwd",
"source_id",
"tag_kwd",
"to_entity_kwd",
"toc_kwd",
"doc_type_kwd",
"available_int",
},
Filter: map[string]interface{}{
"doc_id": req.DocID,
},
@@ -887,8 +916,12 @@ func (s *ChunkService) List(req *service.ListChunksRequest, userID string) (*ser
result["positions"] = v
case "id":
result["chunk_id"] = v
case "content":
case "content_with_weight":
result["content_with_weight"] = v
case "content":
if _, ok := result["content_with_weight"]; !ok {
result["content_with_weight"] = v
}
case "docnm":
result["docnm_kwd"] = v
case "important_keywords":

View File

@@ -16,6 +16,7 @@ import (
"ragflow/internal/service/document"
"ragflow/internal/storage"
"reflect"
"slices"
"strings"
"testing"
"time"
@@ -278,6 +279,79 @@ func TestParseRejectsRunningDocument(t *testing.T) {
}
}
func TestListBuildsMatchTextExprForKeywords(t *testing.T) {
db := setupChunkTestDB(t)
pushChunkTestDB(t, db)
userID := "user-1"
tenantID := "tenant-1"
datasetID := "kb-1"
documentID := "doc-1"
insertChunkTestUserTenant(t, userID, tenantID)
insertChunkTestKB(t, datasetID, tenantID)
insertChunkTestDoc(t, documentID, datasetID)
engine := &listChunksSearchEngine{}
svc := &ChunkService{
docEngine: engine,
kbDAO: dao.NewKnowledgebaseDAO(),
userTenantDAO: dao.NewUserTenantDAO(),
documentDAO: dao.NewDocumentDAO(),
}
page := 2
size := 5
resp, err := svc.List(&service.ListChunksRequest{
DatasetID: datasetID,
DocID: documentID,
Page: &page,
Size: &size,
Keywords: " invoice terms ",
}, userID)
if err != nil {
t.Fatalf("List() error = %v", err)
}
if resp.Total != 1 {
t.Fatalf("total = %d, want 1", resp.Total)
}
if engine.searchReq == nil {
t.Fatal("expected Search to be called")
}
if engine.searchReq.Offset != 5 || engine.searchReq.Limit != 5 {
t.Fatalf("pagination = offset %d limit %d, want offset 5 limit 5", engine.searchReq.Offset, engine.searchReq.Limit)
}
if !reflect.DeepEqual(engine.searchReq.KbIDs, []string{datasetID}) {
t.Fatalf("KbIDs = %#v, want %#v", engine.searchReq.KbIDs, []string{datasetID})
}
if got := engine.searchReq.Filter["doc_id"]; got != documentID {
t.Fatalf("doc_id filter = %#v, want %q", got, documentID)
}
if slices.Contains(engine.searchReq.SelectFields, "content") {
t.Fatalf("SelectFields = %#v, should not request content with content_with_weight", engine.searchReq.SelectFields)
}
for _, field := range []string{"content_with_weight", "img_id", "position_int"} {
if !slices.Contains(engine.searchReq.SelectFields, field) {
t.Fatalf("SelectFields = %#v, missing %q", engine.searchReq.SelectFields, field)
}
}
if got := resp.Chunks[0]["content_with_weight"]; got != "weighted invoice terms body" {
t.Fatalf("formatted content_with_weight = %#v, want %q", got, "weighted invoice terms body")
}
if len(engine.searchReq.MatchExprs) != 1 {
t.Fatalf("MatchExprs length = %d, want 1", len(engine.searchReq.MatchExprs))
}
matchText, ok := engine.searchReq.MatchExprs[0].(*types.MatchTextExpr)
if !ok {
t.Fatalf("MatchExprs[0] = %T, want *types.MatchTextExpr", engine.searchReq.MatchExprs[0])
}
if matchText.MatchingText != "invoice terms" {
t.Fatalf("MatchingText = %q, want %q", matchText.MatchingText, "invoice terms")
}
if matchText.TopN != size {
t.Fatalf("TopN = %d, want %d", matchText.TopN, size)
}
}
func TestAddChunkSuccess(t *testing.T) {
ctx := t.Context()
db := setupChunkTestDB(t)
@@ -1032,6 +1106,26 @@ func (e *addChunkTestEngine) InsertChunks(_ context.Context, chunks []map[string
return nil, e.insertErr
}
type listChunksSearchEngine struct {
parseTestDocEngine
searchReq *types.SearchRequest
}
func (e *listChunksSearchEngine) Search(_ context.Context, req *types.SearchRequest) (*types.SearchResult, error) {
e.searchReq = req
return &types.SearchResult{
Chunks: []map[string]interface{}{
{
"id": "chunk-1",
"content": "plain invoice terms body",
"content_with_weight": "weighted invoice terms body",
"doc_id": "doc-1",
},
},
Total: 1,
}, nil
}
type chunkImageStorage struct {
exists bool
oldBinary []byte