Skip to content

Commit 3b129aa

Browse files
authored
Explain SearchOptions and fix ToSearchOptions (#26542)
Follow #26012 #26490. A detailed description has been added to the comment.
1 parent 1432d4e commit 3b129aa

File tree

3 files changed

+35
-22
lines changed

3 files changed

+35
-22
lines changed

modules/indexer/issues/db/options.go

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
)
1515

1616
func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_model.IssuesOptions, error) {
17+
// See the comment of issues_model.SearchOptions for the reason why we need to convert
1718
convertID := func(id *int64) int64 {
1819
if id == nil {
1920
return 0

modules/indexer/issues/dboptions.go

+19-21
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp
1717
IsClosed: opts.IsClosed,
1818
}
1919

20-
if opts.ProjectID != 0 {
21-
searchOpt.ProjectID = &opts.ProjectID
22-
}
23-
2420
if len(opts.LabelIDs) == 1 && opts.LabelIDs[0] == 0 {
2521
searchOpt.NoLabelOnly = true
2622
} else {
@@ -41,25 +37,27 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp
4137
searchOpt.MilestoneIDs = opts.MilestoneIDs
4238
}
4339

44-
if opts.AssigneeID > 0 {
45-
searchOpt.AssigneeID = &opts.AssigneeID
46-
}
47-
if opts.PosterID > 0 {
48-
searchOpt.PosterID = &opts.PosterID
49-
}
50-
if opts.MentionedID > 0 {
51-
searchOpt.MentionID = &opts.MentionedID
52-
}
53-
if opts.ReviewedID > 0 {
54-
searchOpt.ReviewedID = &opts.ReviewedID
55-
}
56-
if opts.ReviewRequestedID > 0 {
57-
searchOpt.ReviewRequestedID = &opts.ReviewRequestedID
58-
}
59-
if opts.SubscriberID > 0 {
60-
searchOpt.SubscriberID = &opts.SubscriberID
40+
// See the comment of issues_model.SearchOptions for the reason why we need to convert
41+
convertID := func(id int64) *int64 {
42+
if id > 0 {
43+
return &id
44+
}
45+
if id == db.NoConditionID {
46+
var zero int64
47+
return &zero
48+
}
49+
return nil
6150
}
6251

52+
searchOpt.ProjectID = convertID(opts.ProjectID)
53+
searchOpt.ProjectBoardID = convertID(opts.ProjectBoardID)
54+
searchOpt.PosterID = convertID(opts.PosterID)
55+
searchOpt.AssigneeID = convertID(opts.AssigneeID)
56+
searchOpt.MentionID = convertID(opts.MentionedID)
57+
searchOpt.ReviewedID = convertID(opts.ReviewedID)
58+
searchOpt.ReviewRequestedID = convertID(opts.ReviewRequestedID)
59+
searchOpt.SubscriberID = convertID(opts.SubscriberID)
60+
6361
if opts.UpdatedAfterUnix > 0 {
6462
searchOpt.UpdatedAfterUnix = &opts.UpdatedAfterUnix
6563
}

modules/indexer/issues/internal/model.go

+15-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,21 @@ type SearchResult struct {
5656
Hits []Match
5757
}
5858

59-
// SearchOptions represents search options
59+
// SearchOptions represents search options.
60+
//
61+
// It has a slightly different design from database query options.
62+
// In database query options, a field is never a pointer, so it could be confusing when it's zero value:
63+
// Do you want to find data with a field value of 0, or do you not specify the field in the options?
64+
// To avoid this confusion, db introduced db.NoConditionID(-1).
65+
// So zero value means the field is not specified in the search options, and db.NoConditionID means "== 0" or "id NOT IN (SELECT id FROM ...)"
66+
// It's still not ideal, it trapped developers many times.
67+
// And sometimes -1 could be a valid value, like issue ID, negative numbers indicate exclusion.
68+
// Since db.NoConditionID is for "db" (the package name is db), it makes sense not to use it in the indexer:
69+
// Why do bleve/elasticsearch/meilisearch indexers need to know about db.NoConditionID?
70+
// So in SearchOptions, we use pointer for fields which could be not specified,
71+
// and always use the value to filter if it's not nil, even if it's zero or negative.
72+
// It can handle almost all cases, if there is an exception, we can add a new field, like NoLabelOnly.
73+
// Unfortunately, we still use db for the indexer and have to convert between db.NoConditionID and nil for legacy reasons.
6074
type SearchOptions struct {
6175
Keyword string // keyword to search
6276

0 commit comments

Comments
 (0)