Search: Allow query field selection (#116238)

This commit is contained in:
Ryan McKinley
2026-01-14 11:55:05 +00:00
committed by GitHub
parent 987c1fc6b6
commit 040854c8af
11 changed files with 474 additions and 194 deletions
+53 -32
View File
@@ -1182,6 +1182,7 @@ func (b *bleveIndex) getIndex(
return b.index, nil
}
// nolint:gocyclo
func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.ResourceSearchRequest, access authlib.AccessClient) (*bleve.SearchRequest, *resourcepb.ErrorResult) {
ctx, span := tracer.Start(ctx, "search.bleveIndex.toBleveSearchRequest")
defer span.End()
@@ -1240,42 +1241,62 @@ func (b *bleveIndex) toBleveSearchRequest(ctx context.Context, req *resourcepb.R
}
}
if len(req.Query) > 1 && strings.Contains(req.Query, "*") {
// wildcard query is expensive - should be used with caution
wildcard := bleve.NewWildcardQuery(req.Query)
queries = append(queries, wildcard)
}
if len(req.Query) > 1 {
if strings.Contains(req.Query, "*") {
// wildcard query is expensive - should be used with caution
wildcard := bleve.NewWildcardQuery(req.Query)
queries = append(queries, wildcard)
} else {
// When using a
searchrequest.Fields = append(searchrequest.Fields, resource.SEARCH_FIELD_SCORE)
disjoin := bleve.NewDisjunctionQuery()
queries = append(queries, disjoin)
if req.Query != "" && !strings.Contains(req.Query, "*") {
// Add a text query
searchrequest.Fields = append(searchrequest.Fields, resource.SEARCH_FIELD_SCORE)
queryFields := req.QueryFields
if len(queryFields) == 0 {
queryFields = []*resourcepb.ResourceSearchRequest_QueryField{
{
Name: resource.SEARCH_FIELD_TITLE,
Type: resourcepb.QueryFieldType_KEYWORD,
Boost: 10, // exact match -- includes ngrams! If they lived on their own field, we could score them differently
}, {
Name: resource.SEARCH_FIELD_TITLE,
Type: resourcepb.QueryFieldType_TEXT,
Boost: 2, // standard analyzer (with ngrams!)
}, {
Name: resource.SEARCH_FIELD_TITLE_PHRASE,
Type: resourcepb.QueryFieldType_TEXT,
Boost: 5, // standard analyzer
},
}
}
// There are multiple ways to match the query string to documents. The following queries are ordered by priority:
for _, field := range queryFields {
switch field.Type {
case resourcepb.QueryFieldType_TEXT, resourcepb.QueryFieldType_DEFAULT:
q := bleve.NewMatchQuery(removeSmallTerms(req.Query)) // removeSmallTerms should be part of the analyzer
q.SetBoost(float64(field.Boost))
q.SetField(field.Name)
q.Analyzer = standard.Name // analyze the text
q.Operator = query.MatchQueryOperatorAnd // all terms must match
disjoin.AddQuery(q)
// Query 1: Match the exact query string
queryExact := bleve.NewMatchQuery(req.Query)
queryExact.SetBoost(10.0)
queryExact.SetField(resource.SEARCH_FIELD_TITLE)
queryExact.Analyzer = keyword.Name // don't analyze the query input - treat it as a single token
queryExact.Operator = query.MatchQueryOperatorAnd // This doesn't make a difference for keyword analyzer, we add it just to be explicit.
searchQuery := bleve.NewDisjunctionQuery(queryExact)
case resourcepb.QueryFieldType_KEYWORD:
q := bleve.NewMatchQuery(req.Query)
q.SetBoost(float64(field.Boost))
q.SetField(field.Name)
q.Analyzer = keyword.Name // don't analyze the query input - treat it as a single token
disjoin.AddQuery(q)
// Query 2: Phrase query with standard analyzer
queryPhrase := bleve.NewMatchPhraseQuery(req.Query)
queryPhrase.SetBoost(5.0)
queryPhrase.SetField(resource.SEARCH_FIELD_TITLE)
queryPhrase.Analyzer = standard.Name
searchQuery.AddQuery(queryPhrase)
// Query 3: Match query with standard analyzer
queryAnalyzed := bleve.NewMatchQuery(removeSmallTerms(req.Query))
queryAnalyzed.SetField(resource.SEARCH_FIELD_TITLE)
queryAnalyzed.SetBoost(2.0)
queryAnalyzed.Analyzer = standard.Name
queryAnalyzed.Operator = query.MatchQueryOperatorAnd // Make sure all terms from the query are matched
searchQuery.AddQuery(queryAnalyzed)
queries = append(queries, searchQuery)
case resourcepb.QueryFieldType_PHRASE:
q := bleve.NewMatchPhraseQuery(req.Query)
q.SetBoost(float64(field.Boost))
q.SetField(field.Name)
q.Analyzer = standard.Name
disjoin.AddQuery(q)
}
}
}
}
switch len(queries) {