From 9faa09e4c659e9b7e9c4c3f846c114f5f9d906b7 Mon Sep 17 00:00:00 2001 From: fschade Date: Wed, 6 Aug 2025 12:26:16 +0200 Subject: [PATCH] enhancement(search): implement search match highlighting for the content field --- services/search/pkg/opensearch/engine.go | 10 +++++- .../search/pkg/opensearch/engine_convert.go | 9 ++++- .../{os_dsl_query.go => os_dsl_query_root.go} | 12 +++++-- ...uery_test.go => os_dsl_query_root_test.go} | 33 ++++++++++++++++++- 4 files changed, 59 insertions(+), 5 deletions(-) rename services/search/pkg/opensearch/{os_dsl_query.go => os_dsl_query_root.go} (71%) rename services/search/pkg/opensearch/{os_dsl_query_test.go => os_dsl_query_root_test.go} (50%) diff --git a/services/search/pkg/opensearch/engine.go b/services/search/pkg/opensearch/engine.go index a15616e8d..0a58b4a33 100644 --- a/services/search/pkg/opensearch/engine.go +++ b/services/search/pkg/opensearch/engine.go @@ -115,7 +115,15 @@ func (e *Engine) Search(ctx context.Context, sir *searchService.SearchIndexReque ) } - body, err := NewRootQuery(boolQuery).MarshalJSON() + body, err := NewRootQuery(boolQuery, RootQueryOptions{ + Highlight: RootQueryHighlight{ + PreTags: []string{""}, + PostTags: []string{""}, + Fields: map[string]RootQueryHighlight{ + "Content": {}, + }, + }, + }).MarshalJSON() if err != nil { return nil, fmt.Errorf("failed to marshal query: %w", err) } diff --git a/services/search/pkg/opensearch/engine_convert.go b/services/search/pkg/opensearch/engine_convert.go index 7c5cbd028..0c09b7e8e 100644 --- a/services/search/pkg/opensearch/engine_convert.go +++ b/services/search/pkg/opensearch/engine_convert.go @@ -58,7 +58,14 @@ func searchHitToSearchMessageMatch(hit opensearchgoAPI.SearchHit) (*searchMessag MimeType: resource.MimeType, Deleted: resource.Deleted, Tags: resource.Tags, - //Highlights: getFragmentValue(hit.Fragments, "Content", 0), + Highlights: func() string { + contentHighlights, ok := hit.Highlight["Content"] + if !ok { + return "" + } + + return strings.Join(contentHighlights[:], "; ") + }(), Audio: func() *searchMessage.Audio { if !strings.HasPrefix(resource.MimeType, "audio/") { return nil diff --git a/services/search/pkg/opensearch/os_dsl_query.go b/services/search/pkg/opensearch/os_dsl_query_root.go similarity index 71% rename from services/search/pkg/opensearch/os_dsl_query.go rename to services/search/pkg/opensearch/os_dsl_query_root.go index dce75ab42..1dd6805eb 100644 --- a/services/search/pkg/opensearch/os_dsl_query.go +++ b/services/search/pkg/opensearch/os_dsl_query_root.go @@ -9,8 +9,6 @@ type RootQuery struct { options RootQueryOptions } -type RootQueryOptions struct{} - func NewRootQuery(builder Builder, o ...RootQueryOptions) *RootQuery { return &RootQuery{query: builder, options: merge(o...)} } @@ -50,3 +48,13 @@ func (q *RootQuery) String() string { b, _ := q.MarshalJSON() return string(b) } + +type RootQueryOptions struct { + Highlight RootQueryHighlight `json:"highlight,omitempty"` +} + +type RootQueryHighlight struct { + PreTags []string `json:"pre_tags,omitempty"` + PostTags []string `json:"post_tags,omitempty"` + Fields map[string]RootQueryHighlight `json:"fields,omitempty"` +} diff --git a/services/search/pkg/opensearch/os_dsl_query_test.go b/services/search/pkg/opensearch/os_dsl_query_root_test.go similarity index 50% rename from services/search/pkg/opensearch/os_dsl_query_test.go rename to services/search/pkg/opensearch/os_dsl_query_root_test.go index eb7dd650b..d47efa9c4 100644 --- a/services/search/pkg/opensearch/os_dsl_query_test.go +++ b/services/search/pkg/opensearch/os_dsl_query_root_test.go @@ -9,7 +9,7 @@ import ( "github.com/opencloud-eu/opencloud/services/search/pkg/opensearch/internal/test" ) -func TestQuery(t *testing.T) { +func TestRootQuery(t *testing.T) { tests := []opensearchtest.TableTest[opensearch.Builder, map[string]any]{ { Name: "simple", @@ -24,6 +24,37 @@ func TestQuery(t *testing.T) { }, }, }, + { + Name: "highlight", + Got: opensearch.NewRootQuery( + opensearch.NewTermQuery[string]("content").Value("content"), + opensearch.RootQueryOptions{ + Highlight: opensearch.RootQueryHighlight{ + PreTags: []string{""}, + PostTags: []string{""}, + Fields: map[string]opensearch.RootQueryHighlight{ + "content": {}, + }, + }, + }, + ), + Want: map[string]any{ + "query": map[string]any{ + "term": map[string]any{ + "content": map[string]any{ + "value": "content", + }, + }, + }, + "highlight": map[string]any{ + "pre_tags": []string{""}, + "post_tags": []string{""}, + "fields": map[string]any{ + "content": map[string]any{}, + }, + }, + }, + }, } for _, test := range tests {