]> source.dussan.org Git - gitea.git/commitdiff
Add open/closed field support for issue index (#25708)
authortechknowlogick <techknowlogick@gitea.io>
Fri, 7 Jul 2023 17:10:13 +0000 (13:10 -0400)
committerGitHub <noreply@github.com>
Fri, 7 Jul 2023 17:10:13 +0000 (17:10 +0000)
A couple of notes:
* Future changes should refactor arguments into a struct
* This filtering only is supported by meilisearch right now
* Issue index number is bumped which will cause a re-index

12 files changed:
modules/indexer/issues/bleve/bleve.go
modules/indexer/issues/bleve/bleve_test.go
modules/indexer/issues/db/db.go
modules/indexer/issues/elasticsearch/elasticsearch.go
modules/indexer/issues/indexer.go
modules/indexer/issues/indexer_test.go
modules/indexer/issues/internal/indexer.go
modules/indexer/issues/internal/model.go
modules/indexer/issues/meilisearch/meilisearch.go
routers/api/v1/repo/issue.go
routers/web/repo/issue.go
routers/web/user/home.go

index 4cc58acac7846d4e97aa14936cd2d895adb31d7d..c368a67ab58635ab5a0055865d519cb18495d986 100644 (file)
@@ -138,7 +138,7 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error {
 
 // Search searches for issues by given conditions.
 // Returns the matching issue IDs
-func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
+func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
        var repoQueriesP []*query.NumericRangeQuery
        for _, repoID := range repoIDs {
                repoQueriesP = append(repoQueriesP, numericEqualityQuery(repoID, "repo_id"))
index f890f8eb488fed43123f658304380b74d442d0f9..0eb136d22b2766d62bad980b6aec59ee50c23808 100644 (file)
@@ -77,7 +77,7 @@ func TestBleveIndexAndSearch(t *testing.T) {
        }
 
        for _, kw := range keywords {
-               res, err := indexer.Search(context.TODO(), kw.Keyword, []int64{2}, 10, 0)
+               res, err := indexer.Search(context.TODO(), kw.Keyword, []int64{2}, 10, 0, "")
                assert.NoError(t, err)
 
                ids := make([]int64, 0, len(res.Hits))
index 17ed426b384ba739512a530d973b11e75e8b97e5..b054b9d800edb7365479203655a4bb02a3b77ed3 100644 (file)
@@ -36,7 +36,7 @@ func (i *Indexer) Delete(_ context.Context, _ ...int64) error {
 }
 
 // Search searches for issues
-func (i *Indexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
+func (i *Indexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
        total, ids, err := issues_model.SearchIssueIDsByKeyword(ctx, kw, repoIDs, limit, start)
        if err != nil {
                return nil, err
index 62889ea578f670e938e41c41b13239cdb4bc3d4b..cfd3628c18507412367db8db47a6b8f26af4e686 100644 (file)
@@ -140,7 +140,7 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error {
 
 // Search searches for issues by given conditions.
 // Returns the matching issue IDs
-func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
+func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
        kwQuery := elastic.NewMultiMatchQuery(keyword, "title", "content", "comments")
        query := elastic.NewBoolQuery()
        query = query.Must(kwQuery)
index 9e2f13371e4a35092b23a7cdae7cb2f1ebf08217..fe5c5d8f26d3038094a26fa680698b12b10f26a7 100644 (file)
@@ -242,12 +242,18 @@ func UpdateIssueIndexer(issue *issues_model.Issue) {
                        comments = append(comments, comment.Content)
                }
        }
+       issueType := "issue"
+       if issue.IsPull {
+               issueType = "pull"
+       }
        indexerData := &internal.IndexerData{
-               ID:       issue.ID,
-               RepoID:   issue.RepoID,
-               Title:    issue.Title,
-               Content:  issue.Content,
-               Comments: comments,
+               ID:        issue.ID,
+               RepoID:    issue.RepoID,
+               State:     string(issue.State()),
+               IssueType: issueType,
+               Title:     issue.Title,
+               Content:   issue.Content,
+               Comments:  comments,
        }
        log.Debug("Adding to channel: %v", indexerData)
        if err := issueIndexerQueue.Push(indexerData); err != nil {
@@ -278,10 +284,10 @@ func DeleteRepoIssueIndexer(ctx context.Context, repo *repo_model.Repository) {
 
 // SearchIssuesByKeyword search issue ids by keywords and repo id
 // WARNNING: You have to ensure user have permission to visit repoIDs' issues
-func SearchIssuesByKeyword(ctx context.Context, repoIDs []int64, keyword string) ([]int64, error) {
+func SearchIssuesByKeyword(ctx context.Context, repoIDs []int64, keyword, state string) ([]int64, error) {
        var issueIDs []int64
        indexer := *globalIndexer.Load()
-       res, err := indexer.Search(ctx, keyword, repoIDs, 50, 0)
+       res, err := indexer.Search(ctx, keyword, repoIDs, 50, 0, state)
        if err != nil {
                return nil, err
        }
index 5962a4ee9cb76f08c1d28d2c8bd0cb61cb6331f6..757eb2f3d9338e56be44a506f90e73e24c0c8d8f 100644 (file)
@@ -50,19 +50,19 @@ func TestBleveSearchIssues(t *testing.T) {
 
        time.Sleep(5 * time.Second)
 
-       ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2")
+       ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2", "")
        assert.NoError(t, err)
        assert.EqualValues(t, []int64{2}, ids)
 
-       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first")
+       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first", "")
        assert.NoError(t, err)
        assert.EqualValues(t, []int64{1}, ids)
 
-       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for")
+       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for", "")
        assert.NoError(t, err)
        assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
 
-       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good")
+       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good", "")
        assert.NoError(t, err)
        assert.EqualValues(t, []int64{1}, ids)
 }
@@ -73,19 +73,19 @@ func TestDBSearchIssues(t *testing.T) {
        setting.Indexer.IssueType = "db"
        InitIssueIndexer(true)
 
-       ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2")
+       ids, err := SearchIssuesByKeyword(context.TODO(), []int64{1}, "issue2", "")
        assert.NoError(t, err)
        assert.EqualValues(t, []int64{2}, ids)
 
-       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first")
+       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "first", "")
        assert.NoError(t, err)
        assert.EqualValues(t, []int64{1}, ids)
 
-       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for")
+       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "for", "")
        assert.NoError(t, err)
        assert.ElementsMatch(t, []int64{1, 2, 3, 5, 11}, ids)
 
-       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good")
+       ids, err = SearchIssuesByKeyword(context.TODO(), []int64{1}, "good", "")
        assert.NoError(t, err)
        assert.EqualValues(t, []int64{1}, ids)
 }
index 553c8a573cdcbc2fb64520828bdd46e202e0780e..b96517bb80db987b1aa21f2ee76b18e0c13810fd 100644 (file)
@@ -15,7 +15,7 @@ type Indexer interface {
        internal.Indexer
        Index(ctx context.Context, issue []*IndexerData) error
        Delete(ctx context.Context, ids ...int64) error
-       Search(ctx context.Context, kw string, repoIDs []int64, limit, start int) (*SearchResult, error)
+       Search(ctx context.Context, kw string, repoIDs []int64, limit, start int, state string) (*SearchResult, error)
 }
 
 // NewDummyIndexer returns a dummy indexer
@@ -37,6 +37,6 @@ func (d *dummyIndexer) Delete(ctx context.Context, ids ...int64) error {
        return fmt.Errorf("indexer is not ready")
 }
 
-func (d *dummyIndexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int) (*SearchResult, error) {
+func (d *dummyIndexer) Search(ctx context.Context, kw string, repoIDs []int64, limit, start int, state string) (*SearchResult, error) {
        return nil, fmt.Errorf("indexer is not ready")
 }
index 8c206fc1cfcdcb4db47b6990f83c42fcc3bd9c7a..2b52d32302a06fa1a8e926d453a82a0f97eab020 100644 (file)
@@ -5,13 +5,15 @@ package internal
 
 // IndexerData data stored in the issue indexer
 type IndexerData struct {
-       ID       int64    `json:"id"`
-       RepoID   int64    `json:"repo_id"`
-       Title    string   `json:"title"`
-       Content  string   `json:"content"`
-       Comments []string `json:"comments"`
-       IsDelete bool     `json:"is_delete"`
-       IDs      []int64  `json:"ids"`
+       ID        int64    `json:"id"`
+       RepoID    int64    `json:"repo_id"`
+       State     string   `json:"state"` // open, closed, all
+       IssueType string   `json:"type"`  // issue or pull
+       Title     string   `json:"title"`
+       Content   string   `json:"content"`
+       Comments  []string `json:"comments"`
+       IsDelete  bool     `json:"is_delete"`
+       IDs       []int64  `json:"ids"`
 }
 
 // Match represents on search result
index 2a46b1ab15cfd7197da55e62bf712c1f1ddb9c3a..2ea06b576c0b844fd6bc0b681eb9fb386e78c1c5 100644 (file)
@@ -16,7 +16,7 @@ import (
 )
 
 const (
-       issueIndexerLatestVersion = 0
+       issueIndexerLatestVersion = 1
 )
 
 var _ internal.Indexer = &Indexer{}
@@ -70,12 +70,19 @@ func (b *Indexer) Delete(_ context.Context, ids ...int64) error {
 
 // Search searches for issues by given conditions.
 // Returns the matching issue IDs
-func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int) (*internal.SearchResult, error) {
+func (b *Indexer) Search(ctx context.Context, keyword string, repoIDs []int64, limit, start int, state string) (*internal.SearchResult, error) {
        repoFilters := make([]string, 0, len(repoIDs))
        for _, repoID := range repoIDs {
                repoFilters = append(repoFilters, "repo_id = "+strconv.FormatInt(repoID, 10))
        }
        filter := strings.Join(repoFilters, " OR ")
+       if state == "open" || state == "closed" {
+               if filter != "" {
+                       filter = "(" + filter + ") AND state = " + state
+               } else {
+                       filter = "state = " + state
+               }
+       }
        searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(keyword, &meilisearch.SearchRequest{
                Filter: filter,
                Limit:  int64(limit),
index 49252f7a4b49af43ba7da4a00001cf2628e80ccb..e76775ae822266270907344a9d7c8a8acc2ceae8 100644 (file)
@@ -195,7 +195,7 @@ func SearchIssues(ctx *context.APIContext) {
        }
        var issueIDs []int64
        if len(keyword) > 0 && len(repoIDs) > 0 {
-               if issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, repoIDs, keyword); err != nil {
+               if issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, repoIDs, keyword, ctx.FormString("state")); err != nil {
                        ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
                        return
                }
@@ -394,7 +394,7 @@ func ListIssues(ctx *context.APIContext) {
        var issueIDs []int64
        var labelIDs []int64
        if len(keyword) > 0 {
-               issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{ctx.Repo.Repository.ID}, keyword)
+               issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{ctx.Repo.Repository.ID}, keyword, ctx.FormString("state"))
                if err != nil {
                        ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err)
                        return
index 65a68386ae73e76e60be76a34997cc2e5ef0f0d4..317f762fb1a21d55ecb6619c47bdc58646b4ca5f 100644 (file)
@@ -189,7 +189,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
 
        var issueIDs []int64
        if len(keyword) > 0 {
-               issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{repo.ID}, keyword)
+               issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{repo.ID}, keyword, ctx.FormString("state"))
                if err != nil {
                        if issue_indexer.IsAvailable(ctx) {
                                ctx.ServerError("issueIndexer.Search", err)
@@ -2466,7 +2466,7 @@ func SearchIssues(ctx *context.Context) {
        }
        var issueIDs []int64
        if len(keyword) > 0 && len(repoIDs) > 0 {
-               if issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, repoIDs, keyword); err != nil {
+               if issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, repoIDs, keyword, ctx.FormString("state")); err != nil {
                        ctx.Error(http.StatusInternalServerError, "SearchIssuesByKeyword", err.Error())
                        return
                }
@@ -2614,7 +2614,7 @@ func ListIssues(ctx *context.Context) {
        var issueIDs []int64
        var labelIDs []int64
        if len(keyword) > 0 {
-               issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{ctx.Repo.Repository.ID}, keyword)
+               issueIDs, err = issue_indexer.SearchIssuesByKeyword(ctx, []int64{ctx.Repo.Repository.ID}, keyword, ctx.FormString("state"))
                if err != nil {
                        ctx.Error(http.StatusInternalServerError, err.Error())
                        return
index 6a89c507a9fd607834e913ff51aa0cb6d3391cda..5f1e0eb4277b81add1607892a244a1be5e5775bd 100644 (file)
@@ -725,7 +725,7 @@ func issueIDsFromSearch(ctx *context.Context, ctxUser *user_model.User, keyword
        if err != nil {
                return nil, fmt.Errorf("GetRepoIDsForIssuesOptions: %w", err)
        }
-       issueIDsFromSearch, err := issue_indexer.SearchIssuesByKeyword(ctx, searchRepoIDs, keyword)
+       issueIDsFromSearch, err := issue_indexer.SearchIssuesByKeyword(ctx, searchRepoIDs, keyword, ctx.FormString("state"))
        if err != nil {
                return nil, fmt.Errorf("SearchIssuesByKeyword: %w", err)
        }