[Feature] add precise search type for Elastic Search (#12869)
* feat: add type query parameters for specifying precise search * feat: add select dropdown in search box Co-authored-by: Lauris BH <lauris@nix.lv> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
parent
b2c20b68a0
commit
c10503afec
12 changed files with 77 additions and 25 deletions
|
@ -53,4 +53,5 @@ func (p *Pagination) SetDefaultParams(ctx *Context) {
|
|||
p.AddParam(ctx, "sort", "SortType")
|
||||
p.AddParam(ctx, "q", "Keyword")
|
||||
p.AddParam(ctx, "tab", "TabName")
|
||||
p.AddParam(ctx, "t", "queryType")
|
||||
}
|
||||
|
|
|
@ -280,12 +280,23 @@ func (b *BleveIndexer) Delete(repoID int64) error {
|
|||
|
||||
// Search searches for files in the specified repo.
|
||||
// Returns the matching file-paths
|
||||
func (b *BleveIndexer) Search(repoIDs []int64, language, keyword string, page, pageSize int) (int64, []*SearchResult, []*SearchResultLanguages, error) {
|
||||
phraseQuery := bleve.NewMatchPhraseQuery(keyword)
|
||||
phraseQuery.FieldVal = "Content"
|
||||
phraseQuery.Analyzer = repoIndexerAnalyzer
|
||||
func (b *BleveIndexer) Search(repoIDs []int64, language, keyword string, page, pageSize int, isMatch bool) (int64, []*SearchResult, []*SearchResultLanguages, error) {
|
||||
var (
|
||||
indexerQuery query.Query
|
||||
keywordQuery query.Query
|
||||
)
|
||||
|
||||
if isMatch {
|
||||
prefixQuery := bleve.NewPrefixQuery(keyword)
|
||||
prefixQuery.FieldVal = "Content"
|
||||
keywordQuery = prefixQuery
|
||||
} else {
|
||||
phraseQuery := bleve.NewMatchPhraseQuery(keyword)
|
||||
phraseQuery.FieldVal = "Content"
|
||||
phraseQuery.Analyzer = repoIndexerAnalyzer
|
||||
keywordQuery = phraseQuery
|
||||
}
|
||||
|
||||
var indexerQuery query.Query
|
||||
if len(repoIDs) > 0 {
|
||||
var repoQueries = make([]query.Query, 0, len(repoIDs))
|
||||
for _, repoID := range repoIDs {
|
||||
|
@ -294,10 +305,10 @@ func (b *BleveIndexer) Search(repoIDs []int64, language, keyword string, page, p
|
|||
|
||||
indexerQuery = bleve.NewConjunctionQuery(
|
||||
bleve.NewDisjunctionQuery(repoQueries...),
|
||||
phraseQuery,
|
||||
keywordQuery,
|
||||
)
|
||||
} else {
|
||||
indexerQuery = phraseQuery
|
||||
indexerQuery = keywordQuery
|
||||
}
|
||||
|
||||
// Save for reuse without language filter
|
||||
|
|
|
@ -27,6 +27,10 @@ import (
|
|||
|
||||
const (
|
||||
esRepoIndexerLatestVersion = 1
|
||||
// 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
|
||||
esMultiMatchTypeBestFields = "best_fields"
|
||||
esMultiMatchTypePhrasePrefix = "phrase_prefix"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -330,8 +334,13 @@ func extractAggs(searchResult *elastic.SearchResult) []*SearchResultLanguages {
|
|||
}
|
||||
|
||||
// Search searches for codes and language stats by given conditions.
|
||||
func (b *ElasticSearchIndexer) Search(repoIDs []int64, language, keyword string, page, pageSize int) (int64, []*SearchResult, []*SearchResultLanguages, error) {
|
||||
kwQuery := elastic.NewMultiMatchQuery(keyword, "content")
|
||||
func (b *ElasticSearchIndexer) Search(repoIDs []int64, language, keyword string, page, pageSize int, isMatch bool) (int64, []*SearchResult, []*SearchResultLanguages, error) {
|
||||
searchType := esMultiMatchTypeBestFields
|
||||
if isMatch {
|
||||
searchType = esMultiMatchTypePhrasePrefix
|
||||
}
|
||||
|
||||
kwQuery := elastic.NewMultiMatchQuery(keyword, "content").Type(searchType)
|
||||
query := elastic.NewBoolQuery()
|
||||
query = query.Must(kwQuery)
|
||||
if len(repoIDs) > 0 {
|
||||
|
|
|
@ -43,7 +43,7 @@ type SearchResultLanguages struct {
|
|||
type Indexer interface {
|
||||
Index(repo *models.Repository, sha string, changes *repoChanges) error
|
||||
Delete(repoID int64) error
|
||||
Search(repoIDs []int64, language, keyword string, page, pageSize int) (int64, []*SearchResult, []*SearchResultLanguages, error)
|
||||
Search(repoIDs []int64, language, keyword string, page, pageSize int, isMatch bool) (int64, []*SearchResult, []*SearchResultLanguages, error)
|
||||
Close()
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ func testIndexer(name string, t *testing.T, indexer Indexer) {
|
|||
|
||||
for _, kw := range keywords {
|
||||
t.Run(kw.Keyword, func(t *testing.T) {
|
||||
total, res, langs, err := indexer.Search(kw.RepoIDs, "", kw.Keyword, 1, 10)
|
||||
total, res, langs, err := indexer.Search(kw.RepoIDs, "", kw.Keyword, 1, 10, false)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, len(kw.IDs), total)
|
||||
assert.EqualValues(t, kw.Langs, len(langs))
|
||||
|
|
|
@ -106,12 +106,12 @@ func searchResult(result *SearchResult, startIndex, endIndex int) (*Result, erro
|
|||
}
|
||||
|
||||
// PerformSearch perform a search on a repository
|
||||
func PerformSearch(repoIDs []int64, language, keyword string, page, pageSize int) (int, []*Result, []*SearchResultLanguages, error) {
|
||||
func PerformSearch(repoIDs []int64, language, keyword string, page, pageSize int, isMatch bool) (int, []*Result, []*SearchResultLanguages, error) {
|
||||
if len(keyword) == 0 {
|
||||
return 0, nil, nil, nil
|
||||
}
|
||||
|
||||
total, results, resultLanguages, err := indexer.Search(repoIDs, language, keyword, page, pageSize)
|
||||
total, results, resultLanguages, err := indexer.Search(repoIDs, language, keyword, page, pageSize, isMatch)
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
|
|
|
@ -73,12 +73,12 @@ func (w *wrappedIndexer) Delete(repoID int64) error {
|
|||
return indexer.Delete(repoID)
|
||||
}
|
||||
|
||||
func (w *wrappedIndexer) Search(repoIDs []int64, language, keyword string, page, pageSize int) (int64, []*SearchResult, []*SearchResultLanguages, error) {
|
||||
func (w *wrappedIndexer) Search(repoIDs []int64, language, keyword string, page, pageSize int, isMatch bool) (int64, []*SearchResult, []*SearchResultLanguages, error) {
|
||||
indexer, err := w.get()
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
return indexer.Search(repoIDs, language, keyword, page, pageSize)
|
||||
return indexer.Search(repoIDs, language, keyword, page, pageSize, isMatch)
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue