Search: Allow query field selection (#116238)
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user