aboutsummaryrefslogtreecommitdiffstats
path: root/modules/indexer/issues/elasticsearch
diff options
context:
space:
mode:
Diffstat (limited to 'modules/indexer/issues/elasticsearch')
-rw-r--r--modules/indexer/issues/elasticsearch/elasticsearch.go44
-rw-r--r--modules/indexer/issues/elasticsearch/elasticsearch_test.go18
2 files changed, 35 insertions, 27 deletions
diff --git a/modules/indexer/issues/elasticsearch/elasticsearch.go b/modules/indexer/issues/elasticsearch/elasticsearch.go
index 4c293f3f2a..9d627466ef 100644
--- a/modules/indexer/issues/elasticsearch/elasticsearch.go
+++ b/modules/indexer/issues/elasticsearch/elasticsearch.go
@@ -5,14 +5,15 @@ package elasticsearch
import (
"context"
- "fmt"
"strconv"
"strings"
"code.gitea.io/gitea/modules/graceful"
+ "code.gitea.io/gitea/modules/indexer"
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
inner_elasticsearch "code.gitea.io/gitea/modules/indexer/internal/elasticsearch"
"code.gitea.io/gitea/modules/indexer/issues/internal"
+ "code.gitea.io/gitea/modules/util"
"github.com/olivere/elastic/v7"
)
@@ -33,6 +34,11 @@ type Indexer struct {
indexer_internal.Indexer // do not composite inner_elasticsearch.Indexer directly to avoid exposing too much
}
+func (b *Indexer) SupportedSearchModes() []indexer.SearchMode {
+ // TODO: es supports fuzzy search, but our code doesn't at the moment, and actually the default fuzziness is already "AUTO"
+ return indexer.SearchModesExactWords()
+}
+
// NewIndexer creates a new elasticsearch indexer
func NewIndexer(url, indexerName string) *Indexer {
inner := inner_elasticsearch.NewIndexer(url, indexerName, issueIndexerLatestVersion, defaultMapping)
@@ -89,7 +95,7 @@ func (b *Indexer) Index(ctx context.Context, issues ...*internal.IndexerData) er
issue := issues[0]
_, err := b.inner.Client.Index().
Index(b.inner.VersionedIndexName()).
- Id(fmt.Sprintf("%d", issue.ID)).
+ Id(strconv.FormatInt(issue.ID, 10)).
BodyJson(issue).
Do(ctx)
return err
@@ -100,7 +106,7 @@ func (b *Indexer) Index(ctx context.Context, issues ...*internal.IndexerData) er
reqs = append(reqs,
elastic.NewBulkIndexRequest().
Index(b.inner.VersionedIndexName()).
- Id(fmt.Sprintf("%d", issue.ID)).
+ Id(strconv.FormatInt(issue.ID, 10)).
Doc(issue),
)
}
@@ -119,7 +125,7 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error {
} else if len(ids) == 1 {
_, err := b.inner.Client.Delete().
Index(b.inner.VersionedIndexName()).
- Id(fmt.Sprintf("%d", ids[0])).
+ Id(strconv.FormatInt(ids[0], 10)).
Do(ctx)
return err
}
@@ -129,7 +135,7 @@ func (b *Indexer) Delete(ctx context.Context, ids ...int64) error {
reqs = append(reqs,
elastic.NewBulkDeleteRequest().
Index(b.inner.VersionedIndexName()).
- Id(fmt.Sprintf("%d", id)),
+ Id(strconv.FormatInt(id, 10)),
)
}
@@ -146,12 +152,12 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
query := elastic.NewBoolQuery()
if options.Keyword != "" {
- searchType := esMultiMatchTypePhrasePrefix
- if options.IsFuzzyKeyword {
- searchType = esMultiMatchTypeBestFields
+ searchMode := util.IfZero(options.SearchMode, b.SupportedSearchModes()[0].ModeValue)
+ if searchMode == indexer.SearchModeExact {
+ query.Must(elastic.NewMultiMatchQuery(options.Keyword, "title", "content", "comments").Type(esMultiMatchTypePhrasePrefix))
+ } else /* words */ {
+ query.Must(elastic.NewMultiMatchQuery(options.Keyword, "title", "content", "comments").Type(esMultiMatchTypeBestFields).Operator("and"))
}
-
- query.Must(elastic.NewMultiMatchQuery(options.Keyword, "title", "content", "comments").Type(searchType))
}
if len(options.RepoIDs) > 0 {
@@ -205,12 +211,22 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
query.Must(elastic.NewTermQuery("project_board_id", options.ProjectColumnID.Value()))
}
- if options.PosterID.Has() {
- query.Must(elastic.NewTermQuery("poster_id", options.PosterID.Value()))
+ if options.PosterID != "" {
+ // "(none)" becomes 0, it means no poster
+ posterIDInt64, _ := strconv.ParseInt(options.PosterID, 10, 64)
+ query.Must(elastic.NewTermQuery("poster_id", posterIDInt64))
}
- if options.AssigneeID.Has() {
- query.Must(elastic.NewTermQuery("assignee_id", options.AssigneeID.Value()))
+ if options.AssigneeID != "" {
+ if options.AssigneeID == "(any)" {
+ q := elastic.NewRangeQuery("assignee_id")
+ q.Gte(1)
+ query.Must(q)
+ } else {
+ // "(none)" becomes 0, it means no assignee
+ assigneeIDInt64, _ := strconv.ParseInt(options.AssigneeID, 10, 64)
+ query.Must(elastic.NewTermQuery("assignee_id", assigneeIDInt64))
+ }
}
if options.MentionID.Has() {
diff --git a/modules/indexer/issues/elasticsearch/elasticsearch_test.go b/modules/indexer/issues/elasticsearch/elasticsearch_test.go
index ffd85b1aa1..dc329c07dd 100644
--- a/modules/indexer/issues/elasticsearch/elasticsearch_test.go
+++ b/modules/indexer/issues/elasticsearch/elasticsearch_test.go
@@ -11,6 +11,8 @@ import (
"time"
"code.gitea.io/gitea/modules/indexer/issues/internal/tests"
+
+ "github.com/stretchr/testify/require"
)
func TestElasticsearchIndexer(t *testing.T) {
@@ -26,20 +28,10 @@ func TestElasticsearchIndexer(t *testing.T) {
}
}
- ok := false
- for i := 0; i < 60; i++ {
+ require.Eventually(t, func() bool {
resp, err := http.Get(url)
- if err == nil && resp.StatusCode == http.StatusOK {
- ok = true
- break
- }
- t.Logf("Waiting for elasticsearch to be up: %v", err)
- time.Sleep(time.Second)
- }
- if !ok {
- t.Fatalf("Failed to wait for elasticsearch to be up")
- return
- }
+ return err == nil && resp.StatusCode == http.StatusOK
+ }, time.Minute, time.Second, "Expected elasticsearch to be up")
indexer := NewIndexer(url, fmt.Sprintf("test_elasticsearch_indexer_%d", time.Now().Unix()))
defer indexer.Close()