feat: Add support for using highlight without returning the field as the output field. (#45984)

relate: https://github.com/milvus-io/milvus/issues/42589

Signed-off-by: aoiasd <zhicheng.yue@zilliz.com>
This commit is contained in:
aoiasd 2025-12-04 10:35:11 +08:00 committed by GitHub
parent 43fe215787
commit 8efe9ccac6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 13 deletions

View File

@ -36,6 +36,7 @@ const (
type Highlighter interface { type Highlighter interface {
AsSearchPipelineOperator(t *searchTask) (operator, error) AsSearchPipelineOperator(t *searchTask) (operator, error)
FieldIDs() []int64
} }
// highlight task for one field // highlight task for one field
@ -114,18 +115,26 @@ func (h *LexicalHighlighter) addTaskWithQuery(fieldID int64, query *highlightQue
}) })
} }
func (h *LexicalHighlighter) AsSearchPipelineOperator(t *searchTask) (operator, error) { func (h *LexicalHighlighter) initHighlightQueries(t *searchTask) error {
// add query to highlight tasks // add query to highlight tasks
for _, query := range h.queries { for _, query := range h.queries {
fieldID, ok := t.schema.MapFieldID(query.fieldName) fieldID, ok := t.schema.MapFieldID(query.fieldName)
if !ok { if !ok {
return nil, merr.WrapErrParameterInvalidMsg("highlight field not found in schema: %s", query.fieldName) return merr.WrapErrParameterInvalidMsg("highlight field not found in schema: %s", query.fieldName)
} }
h.addTaskWithQuery(fieldID, query) h.addTaskWithQuery(fieldID, query)
} }
return nil
}
func (h *LexicalHighlighter) AsSearchPipelineOperator(t *searchTask) (operator, error) {
return newLexicalHighlightOperator(t, lo.Values(h.tasks)) return newLexicalHighlightOperator(t, lo.Values(h.tasks))
} }
func (h *LexicalHighlighter) FieldIDs() []int64 {
return lo.Keys(h.tasks)
}
func NewLexicalHighlighter(highlighter *commonpb.Highlighter) (*LexicalHighlighter, error) { func NewLexicalHighlighter(highlighter *commonpb.Highlighter) (*LexicalHighlighter, error) {
params := funcutil.KeyValuePair2Map(highlighter.GetParams()) params := funcutil.KeyValuePair2Map(highlighter.GetParams())
h := &LexicalHighlighter{ h := &LexicalHighlighter{

View File

@ -602,7 +602,12 @@ func (t *searchTask) createLexicalHighlighter(highlighter *commonpb.Highlighter,
if err != nil { if err != nil {
return err return err
} }
return h.addTaskWithSearchText(fieldId, fieldName, analyzerName, texts) err = h.addTaskWithSearchText(fieldId, fieldName, analyzerName, texts)
if err != nil {
return err
}
return h.initHighlightQueries(t)
} }
return nil return nil
} }
@ -642,10 +647,24 @@ func (t *searchTask) initSearchRequest(ctx context.Context) error {
} }
} }
analyzer, err := funcutil.GetAttrByKeyFromRepeatedKV(AnalyzerKey, t.request.GetSearchParams())
if err == nil {
t.SearchRequest.AnalyzerName = analyzer
}
t.isIterator = isIterator t.isIterator = isIterator
t.SearchRequest.Offset = offset t.SearchRequest.Offset = offset
t.SearchRequest.FieldId = queryInfo.GetQueryFieldId() t.SearchRequest.FieldId = queryInfo.GetQueryFieldId()
if err := t.addHighlightTask(t.request.GetHighlighter(), queryInfo.GetMetricType(), queryInfo.GetQueryFieldId(), t.request.GetPlaceholderGroup(), t.SearchRequest.GetAnalyzerName()); err != nil {
return err
}
// add highlight field ids to output fields id
if t.highlighter != nil {
t.SearchRequest.OutputFieldsId = append(t.SearchRequest.OutputFieldsId, t.highlighter.FieldIDs()...)
}
if t.partitionKeyMode { if t.partitionKeyMode {
// isolation has tighter constraint, check first // isolation has tighter constraint, check first
mvErr := setQueryInfoIfMvEnable(queryInfo, t, plan) mvErr := setQueryInfoIfMvEnable(queryInfo, t, plan)
@ -696,16 +715,6 @@ func (t *searchTask) initSearchRequest(ctx context.Context) error {
t.SearchRequest.GroupByFieldId = queryInfo.GroupByFieldId t.SearchRequest.GroupByFieldId = queryInfo.GroupByFieldId
t.SearchRequest.GroupSize = queryInfo.GroupSize t.SearchRequest.GroupSize = queryInfo.GroupSize
if t.SearchRequest.MetricType == metric.BM25 {
analyzer, err := funcutil.GetAttrByKeyFromRepeatedKV(AnalyzerKey, t.request.GetSearchParams())
if err == nil {
t.SearchRequest.AnalyzerName = analyzer
}
}
if err := t.addHighlightTask(t.request.GetHighlighter(), t.SearchRequest.MetricType, t.SearchRequest.FieldId, t.request.GetPlaceholderGroup(), t.SearchRequest.GetAnalyzerName()); err != nil {
return err
}
if embedding.HasNonBM25Functions(t.schema.CollectionSchema.Functions, []int64{queryInfo.GetQueryFieldId()}) { if embedding.HasNonBM25Functions(t.schema.CollectionSchema.Functions, []int64{queryInfo.GetQueryFieldId()}) {
ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-Search-call-function-udf") ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-Search-call-function-udf")
defer sp.End() defer sp.End()