diff --git a/modules/indexer/issues/bleve/bleve.go b/modules/indexer/issues/bleve/bleve.go index 3627ec5079..fd9b92c4dd 100644 --- a/modules/indexer/issues/bleve/bleve.go +++ b/modules/indexer/issues/bleve/bleve.go @@ -11,7 +11,6 @@ import ( indexer_internal "gitea.dev/modules/indexer/internal" inner_bleve "gitea.dev/modules/indexer/internal/bleve" "gitea.dev/modules/indexer/issues/internal" - "gitea.dev/modules/optional" "gitea.dev/modules/util" "github.com/blevesearch/bleve/v2" @@ -88,6 +87,7 @@ func generateIssueIndexMapping() (mapping.IndexMapping, error) { docMapping.AddFieldMappingsAt("poster_id", numberFieldMapping) docMapping.AddFieldMappingsAt("assignee_id", numberFieldMapping) docMapping.AddFieldMappingsAt("assignee_ids", numberFieldMapping) + docMapping.AddFieldMappingsAt("no_assignee", boolFieldMapping) docMapping.AddFieldMappingsAt("mention_ids", numberFieldMapping) docMapping.AddFieldMappingsAt("reviewed_ids", numberFieldMapping) docMapping.AddFieldMappingsAt("review_requested_ids", numberFieldMapping) @@ -261,12 +261,10 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) ( if options.AssigneeID != "" { if options.AssigneeID == "(any)" { - queries = append(queries, bleve.NewDisjunctionQuery( - inner_bleve.NumericRangeInclusiveQuery(optional.Some[int64](1), optional.None[int64](), "assignee_ids"), - inner_bleve.NumericRangeInclusiveQuery(optional.Some[int64](1), optional.None[int64](), "assignee_id"), - )) + queries = append(queries, inner_bleve.BoolFieldQuery(false, "no_assignee")) + } else if options.AssigneeID == "(none)" { + queries = append(queries, inner_bleve.BoolFieldQuery(true, "no_assignee")) } else { - // "(none)" becomes 0, it means no assignee assigneeIDInt64, _ := strconv.ParseInt(options.AssigneeID, 10, 64) queries = append(queries, bleve.NewDisjunctionQuery( inner_bleve.NumericEqualityQuery(assigneeIDInt64, "assignee_ids"), diff --git a/modules/indexer/issues/bleve/bleve_test.go b/modules/indexer/issues/bleve/bleve_test.go index ccd7ab7b92..8d1e323125 100644 --- a/modules/indexer/issues/bleve/bleve_test.go +++ b/modules/indexer/issues/bleve/bleve_test.go @@ -6,7 +6,11 @@ package bleve import ( "testing" + "gitea.dev/modules/indexer/issues/internal" "gitea.dev/modules/indexer/issues/internal/tests" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestBleveIndexer(t *testing.T) { @@ -16,3 +20,56 @@ func TestBleveIndexer(t *testing.T) { tests.TestIndexer(t, indexer) } + +func TestBleveIndexerNoAssignee(t *testing.T) { + dir := t.TempDir() + indexer := NewIndexer(dir) + defer indexer.Close() + + _, err := indexer.Init(t.Context()) + require.NoError(t, err) + + require.NoError(t, indexer.Index(t.Context(), + &internal.IndexerData{ID: 1, Title: "assigned through assignee_ids", AssigneeIDs: []int64{2}}, + &internal.IndexerData{ID: 2, Title: "unassigned", NoAssignee: true}, + )) + + testCases := []struct { + name string + opts *internal.SearchOptions + expectedIDs []int64 + }{ + { + name: "none", + opts: &internal.SearchOptions{AssigneeID: "(none)"}, + expectedIDs: []int64{2}, + }, + { + name: "any", + opts: &internal.SearchOptions{AssigneeID: "(any)"}, + expectedIDs: []int64{1}, + }, + { + name: "specific", + opts: &internal.SearchOptions{AssigneeID: "2"}, + expectedIDs: []int64{1}, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + result, err := indexer.Search(t.Context(), testCase.opts) + require.NoError(t, err) + assert.Equal(t, int64(len(testCase.expectedIDs)), result.Total) + assert.Equal(t, testCase.expectedIDs, searchResultIDs(result)) + }) + } +} + +func searchResultIDs(result *internal.SearchResult) []int64 { + ids := make([]int64, 0, len(result.Hits)) + for _, hit := range result.Hits { + ids = append(ids, hit.ID) + } + return ids +} diff --git a/modules/indexer/issues/internal/model.go b/modules/indexer/issues/internal/model.go index a48adb3c60..a19a4b1f3c 100644 --- a/modules/indexer/issues/internal/model.go +++ b/modules/indexer/issues/internal/model.go @@ -36,6 +36,7 @@ type IndexerData struct { PosterID int64 `json:"poster_id"` AssigneeID int64 `json:"assignee_id"` AssigneeIDs []int64 `json:"assignee_ids"` + NoAssignee bool `json:"no_assignee"` // True if AssigneeID and AssigneeIDs are empty MentionIDs []int64 `json:"mention_ids"` ReviewedIDs []int64 `json:"reviewed_ids"` ReviewRequestedIDs []int64 `json:"review_requested_ids"` diff --git a/modules/indexer/issues/internal/tests/tests.go b/modules/indexer/issues/internal/tests/tests.go index 276f3fb5bb..81489a7ecd 100644 --- a/modules/indexer/issues/internal/tests/tests.go +++ b/modules/indexer/issues/internal/tests/tests.go @@ -395,10 +395,10 @@ var cases = []*testIndexerCase{ Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Len(t, result.Hits, 5) for _, v := range result.Hits { - assert.Equal(t, int64(0), data[v.ID].AssigneeID) + assert.True(t, data[v.ID].NoAssignee) } assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool { - return v.AssigneeID == 0 + return v.NoAssignee }), result.Total) }, }, @@ -630,10 +630,10 @@ var cases = []*testIndexerCase{ Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { assert.Len(t, result.Hits, 180) for _, v := range result.Hits { - assert.GreaterOrEqual(t, data[v.ID].AssigneeID, int64(1)) + assert.False(t, data[v.ID].NoAssignee) } assert.Equal(t, countIndexerData(data, func(v *internal.IndexerData) bool { - return v.AssigneeID >= 1 + return !v.NoAssignee }), result.Total) }, }, @@ -686,6 +686,7 @@ func generateDefaultIndexerData() []*internal.IndexerData { for i := range projectIDs { projectIDs[i] = int64(i) + 1 // projectID should not be 0 } + assigneeID := issueIndex % 10 data = append(data, &internal.IndexerData{ ID: id, @@ -702,7 +703,8 @@ func generateDefaultIndexerData() []*internal.IndexerData { ProjectIDs: projectIDs, NoProject: len(projectIDs) == 0, PosterID: id%10 + 1, // PosterID should not be 0 - AssigneeID: issueIndex % 10, + AssigneeID: assigneeID, + NoAssignee: assigneeID == 0, MentionIDs: mentionIDs, ReviewedIDs: reviewedIDs, ReviewRequestedIDs: reviewRequestedIDs, diff --git a/modules/indexer/issues/util.go b/modules/indexer/issues/util.go index 0db424a350..b0ed7facc7 100644 --- a/modules/indexer/issues/util.go +++ b/modules/indexer/issues/util.go @@ -119,6 +119,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD PosterID: issue.PosterID, AssigneeID: issue.AssigneeID, AssigneeIDs: assigneeIDs, + NoAssignee: issue.AssigneeID == 0 && len(assigneeIDs) == 0, MentionIDs: mentionIDs, ReviewedIDs: reviewedIDs, ReviewRequestedIDs: reviewRequestedIDs,