mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 12:53:43 +01:00 
			
		
		
		
	Add is_archived option for issue indexer (#32735)
				
					
				
			Try to fix #32697 Reason: `is_archived` is already defined in the query options, but it is not implemented in the indexer.
This commit is contained in:
		
							parent
							
								
									39a01016cd
								
							
						
					
					
						commit
						d43620e7bc
					
				@ -23,7 +23,7 @@ import (
 | 
				
			|||||||
const (
 | 
					const (
 | 
				
			||||||
	issueIndexerAnalyzer      = "issueIndexer"
 | 
						issueIndexerAnalyzer      = "issueIndexer"
 | 
				
			||||||
	issueIndexerDocType       = "issueIndexerDocType"
 | 
						issueIndexerDocType       = "issueIndexerDocType"
 | 
				
			||||||
	issueIndexerLatestVersion = 4
 | 
						issueIndexerLatestVersion = 5
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const unicodeNormalizeName = "unicodeNormalize"
 | 
					const unicodeNormalizeName = "unicodeNormalize"
 | 
				
			||||||
@ -75,6 +75,7 @@ func generateIssueIndexMapping() (mapping.IndexMapping, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	docMapping.AddFieldMappingsAt("is_pull", boolFieldMapping)
 | 
						docMapping.AddFieldMappingsAt("is_pull", boolFieldMapping)
 | 
				
			||||||
	docMapping.AddFieldMappingsAt("is_closed", boolFieldMapping)
 | 
						docMapping.AddFieldMappingsAt("is_closed", boolFieldMapping)
 | 
				
			||||||
 | 
						docMapping.AddFieldMappingsAt("is_archived", boolFieldMapping)
 | 
				
			||||||
	docMapping.AddFieldMappingsAt("label_ids", numberFieldMapping)
 | 
						docMapping.AddFieldMappingsAt("label_ids", numberFieldMapping)
 | 
				
			||||||
	docMapping.AddFieldMappingsAt("no_label", boolFieldMapping)
 | 
						docMapping.AddFieldMappingsAt("no_label", boolFieldMapping)
 | 
				
			||||||
	docMapping.AddFieldMappingsAt("milestone_id", numberFieldMapping)
 | 
						docMapping.AddFieldMappingsAt("milestone_id", numberFieldMapping)
 | 
				
			||||||
@ -185,6 +186,9 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
 | 
				
			|||||||
	if options.IsClosed.Has() {
 | 
						if options.IsClosed.Has() {
 | 
				
			||||||
		queries = append(queries, inner_bleve.BoolFieldQuery(options.IsClosed.Value(), "is_closed"))
 | 
							queries = append(queries, inner_bleve.BoolFieldQuery(options.IsClosed.Value(), "is_closed"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if options.IsArchived.Has() {
 | 
				
			||||||
 | 
							queries = append(queries, inner_bleve.BoolFieldQuery(options.IsArchived.Value(), "is_archived"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if options.NoLabelOnly {
 | 
						if options.NoLabelOnly {
 | 
				
			||||||
		queries = append(queries, inner_bleve.BoolFieldQuery(true, "no_label"))
 | 
							queries = append(queries, inner_bleve.BoolFieldQuery(true, "no_label"))
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,7 @@ func ToDBOptions(ctx context.Context, options *internal.SearchOptions) (*issue_m
 | 
				
			|||||||
		UpdatedAfterUnix:   options.UpdatedAfterUnix.Value(),
 | 
							UpdatedAfterUnix:   options.UpdatedAfterUnix.Value(),
 | 
				
			||||||
		UpdatedBeforeUnix:  options.UpdatedBeforeUnix.Value(),
 | 
							UpdatedBeforeUnix:  options.UpdatedBeforeUnix.Value(),
 | 
				
			||||||
		PriorityRepoID:     0,
 | 
							PriorityRepoID:     0,
 | 
				
			||||||
		IsArchived:         optional.None[bool](),
 | 
							IsArchived:         options.IsArchived,
 | 
				
			||||||
		Org:                nil,
 | 
							Org:                nil,
 | 
				
			||||||
		Team:               nil,
 | 
							Team:               nil,
 | 
				
			||||||
		User:               nil,
 | 
							User:               nil,
 | 
				
			||||||
 | 
				
			|||||||
@ -11,11 +11,12 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOptions {
 | 
					func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOptions {
 | 
				
			||||||
	searchOpt := &SearchOptions{
 | 
						searchOpt := &SearchOptions{
 | 
				
			||||||
		Keyword:   keyword,
 | 
							Keyword:    keyword,
 | 
				
			||||||
		RepoIDs:   opts.RepoIDs,
 | 
							RepoIDs:    opts.RepoIDs,
 | 
				
			||||||
		AllPublic: opts.AllPublic,
 | 
							AllPublic:  opts.AllPublic,
 | 
				
			||||||
		IsPull:    opts.IsPull,
 | 
							IsPull:     opts.IsPull,
 | 
				
			||||||
		IsClosed:  opts.IsClosed,
 | 
							IsClosed:   opts.IsClosed,
 | 
				
			||||||
 | 
							IsArchived: opts.IsArchived,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(opts.LabelIDs) == 1 && opts.LabelIDs[0] == 0 {
 | 
						if len(opts.LabelIDs) == 1 && opts.LabelIDs[0] == 0 {
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	issueIndexerLatestVersion = 1
 | 
						issueIndexerLatestVersion = 2
 | 
				
			||||||
	// multi-match-types, currently only 2 types are used
 | 
						// multi-match-types, currently only 2 types are used
 | 
				
			||||||
	// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
 | 
						// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
 | 
				
			||||||
	esMultiMatchTypeBestFields   = "best_fields"
 | 
						esMultiMatchTypeBestFields   = "best_fields"
 | 
				
			||||||
@ -58,6 +58,7 @@ const (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			"is_pull": { "type": "boolean", "index": true },
 | 
								"is_pull": { "type": "boolean", "index": true },
 | 
				
			||||||
			"is_closed": { "type": "boolean", "index": true },
 | 
								"is_closed": { "type": "boolean", "index": true },
 | 
				
			||||||
 | 
								"is_archived": { "type": "boolean", "index": true },
 | 
				
			||||||
			"label_ids": { "type": "integer", "index": true },
 | 
								"label_ids": { "type": "integer", "index": true },
 | 
				
			||||||
			"no_label": { "type": "boolean", "index": true },
 | 
								"no_label": { "type": "boolean", "index": true },
 | 
				
			||||||
			"milestone_id": { "type": "integer", "index": true },
 | 
								"milestone_id": { "type": "integer", "index": true },
 | 
				
			||||||
@ -168,6 +169,9 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
 | 
				
			|||||||
	if options.IsClosed.Has() {
 | 
						if options.IsClosed.Has() {
 | 
				
			||||||
		query.Must(elastic.NewTermQuery("is_closed", options.IsClosed.Value()))
 | 
							query.Must(elastic.NewTermQuery("is_closed", options.IsClosed.Value()))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if options.IsArchived.Has() {
 | 
				
			||||||
 | 
							query.Must(elastic.NewTermQuery("is_archived", options.IsArchived.Value()))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if options.NoLabelOnly {
 | 
						if options.NoLabelOnly {
 | 
				
			||||||
		query.Must(elastic.NewTermQuery("no_label", true))
 | 
							query.Must(elastic.NewTermQuery("no_label", true))
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,7 @@ func TestDBSearchIssues(t *testing.T) {
 | 
				
			|||||||
	t.Run("search issues by ID", searchIssueByID)
 | 
						t.Run("search issues by ID", searchIssueByID)
 | 
				
			||||||
	t.Run("search issues is pr", searchIssueIsPull)
 | 
						t.Run("search issues is pr", searchIssueIsPull)
 | 
				
			||||||
	t.Run("search issues is closed", searchIssueIsClosed)
 | 
						t.Run("search issues is closed", searchIssueIsClosed)
 | 
				
			||||||
 | 
						t.Run("search issues is archived", searchIssueIsArchived)
 | 
				
			||||||
	t.Run("search issues by milestone", searchIssueByMilestoneID)
 | 
						t.Run("search issues by milestone", searchIssueByMilestoneID)
 | 
				
			||||||
	t.Run("search issues by label", searchIssueByLabelID)
 | 
						t.Run("search issues by label", searchIssueByLabelID)
 | 
				
			||||||
	t.Run("search issues by time", searchIssueByTime)
 | 
						t.Run("search issues by time", searchIssueByTime)
 | 
				
			||||||
@ -298,6 +299,33 @@ func searchIssueIsClosed(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func searchIssueIsArchived(t *testing.T) {
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							opts        SearchOptions
 | 
				
			||||||
 | 
							expectedIDs []int64
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								SearchOptions{
 | 
				
			||||||
 | 
									IsArchived: optional.Some(false),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								[]int64{22, 21, 17, 16, 15, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3, 2, 1},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								SearchOptions{
 | 
				
			||||||
 | 
									IsArchived: optional.Some(true),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								[]int64{14},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
 | 
				
			||||||
 | 
							if !assert.NoError(t, err) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							assert.Equal(t, test.expectedIDs, issueIDs)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func searchIssueByMilestoneID(t *testing.T) {
 | 
					func searchIssueByMilestoneID(t *testing.T) {
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		opts        SearchOptions
 | 
							opts        SearchOptions
 | 
				
			||||||
 | 
				
			|||||||
@ -25,6 +25,7 @@ type IndexerData struct {
 | 
				
			|||||||
	// Fields used for filtering
 | 
						// Fields used for filtering
 | 
				
			||||||
	IsPull             bool               `json:"is_pull"`
 | 
						IsPull             bool               `json:"is_pull"`
 | 
				
			||||||
	IsClosed           bool               `json:"is_closed"`
 | 
						IsClosed           bool               `json:"is_closed"`
 | 
				
			||||||
 | 
						IsArchived         bool               `json:"is_archived"`
 | 
				
			||||||
	LabelIDs           []int64            `json:"label_ids"`
 | 
						LabelIDs           []int64            `json:"label_ids"`
 | 
				
			||||||
	NoLabel            bool               `json:"no_label"` // True if LabelIDs is empty
 | 
						NoLabel            bool               `json:"no_label"` // True if LabelIDs is empty
 | 
				
			||||||
	MilestoneID        int64              `json:"milestone_id"`
 | 
						MilestoneID        int64              `json:"milestone_id"`
 | 
				
			||||||
@ -81,8 +82,9 @@ type SearchOptions struct {
 | 
				
			|||||||
	RepoIDs   []int64 // repository IDs which the issues belong to
 | 
						RepoIDs   []int64 // repository IDs which the issues belong to
 | 
				
			||||||
	AllPublic bool    // if include all public repositories
 | 
						AllPublic bool    // if include all public repositories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	IsPull   optional.Option[bool] // if the issues is a pull request
 | 
						IsPull     optional.Option[bool] // if the issues is a pull request
 | 
				
			||||||
	IsClosed optional.Option[bool] // if the issues is closed
 | 
						IsClosed   optional.Option[bool] // if the issues is closed
 | 
				
			||||||
 | 
						IsArchived optional.Option[bool] // if the repo is archived
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	IncludedLabelIDs    []int64 // labels the issues have
 | 
						IncludedLabelIDs    []int64 // labels the issues have
 | 
				
			||||||
	ExcludedLabelIDs    []int64 // labels the issues don't have
 | 
						ExcludedLabelIDs    []int64 // labels the issues don't have
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	issueIndexerLatestVersion = 3
 | 
						issueIndexerLatestVersion = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: make this configurable if necessary
 | 
						// TODO: make this configurable if necessary
 | 
				
			||||||
	maxTotalHits = 10000
 | 
						maxTotalHits = 10000
 | 
				
			||||||
@ -61,6 +61,7 @@ func NewIndexer(url, apiKey, indexerName string) *Indexer {
 | 
				
			|||||||
			"is_public",
 | 
								"is_public",
 | 
				
			||||||
			"is_pull",
 | 
								"is_pull",
 | 
				
			||||||
			"is_closed",
 | 
								"is_closed",
 | 
				
			||||||
 | 
								"is_archived",
 | 
				
			||||||
			"label_ids",
 | 
								"label_ids",
 | 
				
			||||||
			"no_label",
 | 
								"no_label",
 | 
				
			||||||
			"milestone_id",
 | 
								"milestone_id",
 | 
				
			||||||
@ -145,6 +146,9 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
 | 
				
			|||||||
	if options.IsClosed.Has() {
 | 
						if options.IsClosed.Has() {
 | 
				
			||||||
		query.And(inner_meilisearch.NewFilterEq("is_closed", options.IsClosed.Value()))
 | 
							query.And(inner_meilisearch.NewFilterEq("is_closed", options.IsClosed.Value()))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if options.IsArchived.Has() {
 | 
				
			||||||
 | 
							query.And(inner_meilisearch.NewFilterEq("is_archived", options.IsArchived.Value()))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if options.NoLabelOnly {
 | 
						if options.NoLabelOnly {
 | 
				
			||||||
		query.And(inner_meilisearch.NewFilterEq("no_label", true))
 | 
							query.And(inner_meilisearch.NewFilterEq("no_label", true))
 | 
				
			||||||
 | 
				
			|||||||
@ -101,6 +101,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
 | 
				
			|||||||
		Comments:           comments,
 | 
							Comments:           comments,
 | 
				
			||||||
		IsPull:             issue.IsPull,
 | 
							IsPull:             issue.IsPull,
 | 
				
			||||||
		IsClosed:           issue.IsClosed,
 | 
							IsClosed:           issue.IsClosed,
 | 
				
			||||||
 | 
							IsArchived:         issue.Repo.IsArchived,
 | 
				
			||||||
		LabelIDs:           labels,
 | 
							LabelIDs:           labels,
 | 
				
			||||||
		NoLabel:            len(labels) == 0,
 | 
							NoLabel:            len(labels) == 0,
 | 
				
			||||||
		MilestoneID:        issue.MilestoneID,
 | 
							MilestoneID:        issue.MilestoneID,
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/base"
 | 
						"code.gitea.io/gitea/modules/base"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/git"
 | 
						"code.gitea.io/gitea/modules/git"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/indexer/code"
 | 
						"code.gitea.io/gitea/modules/indexer/code"
 | 
				
			||||||
 | 
						issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/indexer/stats"
 | 
						"code.gitea.io/gitea/modules/indexer/stats"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/lfs"
 | 
						"code.gitea.io/gitea/modules/lfs"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
@ -905,6 +906,9 @@ func SettingsPost(ctx *context.Context) {
 | 
				
			|||||||
			log.Error("CleanRepoScheduleTasks for archived repo %s/%s: %v", ctx.Repo.Owner.Name, repo.Name, err)
 | 
								log.Error("CleanRepoScheduleTasks for archived repo %s/%s: %v", ctx.Repo.Owner.Name, repo.Name, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// update issue indexer
 | 
				
			||||||
 | 
							issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ctx.Flash.Success(ctx.Tr("repo.settings.archive.success"))
 | 
							ctx.Flash.Success(ctx.Tr("repo.settings.archive.success"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log.Trace("Repository was archived: %s/%s", ctx.Repo.Owner.Name, repo.Name)
 | 
							log.Trace("Repository was archived: %s/%s", ctx.Repo.Owner.Name, repo.Name)
 | 
				
			||||||
@ -929,6 +933,9 @@ func SettingsPost(ctx *context.Context) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// update issue indexer
 | 
				
			||||||
 | 
							issue_indexer.UpdateRepoIndexer(ctx, repo.ID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ctx.Flash.Success(ctx.Tr("repo.settings.unarchive.success"))
 | 
							ctx.Flash.Success(ctx.Tr("repo.settings.unarchive.success"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log.Trace("Repository was un-archived: %s/%s", ctx.Repo.Owner.Name, repo.Name)
 | 
							log.Trace("Repository was un-archived: %s/%s", ctx.Repo.Owner.Name, repo.Name)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user