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 {
AsSearchPipelineOperator(t *searchTask) (operator, error)
FieldIDs() []int64
}
// 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
for _, query := range h.queries {
fieldID, ok := t.schema.MapFieldID(query.fieldName)
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)
}
return nil
}
func (h *LexicalHighlighter) AsSearchPipelineOperator(t *searchTask) (operator, error) {
return newLexicalHighlightOperator(t, lo.Values(h.tasks))
}
func (h *LexicalHighlighter) FieldIDs() []int64 {
return lo.Keys(h.tasks)
}
func NewLexicalHighlighter(highlighter *commonpb.Highlighter) (*LexicalHighlighter, error) {
params := funcutil.KeyValuePair2Map(highlighter.GetParams())
h := &LexicalHighlighter{

View File

@ -602,7 +602,12 @@ func (t *searchTask) createLexicalHighlighter(highlighter *commonpb.Highlighter,
if err != nil {
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
}
@ -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.SearchRequest.Offset = offset
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 {
// isolation has tighter constraint, check first
mvErr := setQueryInfoIfMvEnable(queryInfo, t, plan)
@ -696,16 +715,6 @@ func (t *searchTask) initSearchRequest(ctx context.Context) error {
t.SearchRequest.GroupByFieldId = queryInfo.GroupByFieldId
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()}) {
ctx, sp := otel.Tracer(typeutil.ProxyRole).Start(ctx, "Proxy-Search-call-function-udf")
defer sp.End()