Files
72243bead7 fix(indexer): index full file paths and real offsets in bleve (#39405)
The bleve path token filter added in
https://github.com/go-gitea/gitea/pull/32210 never generated the full
path of a file, so searching a file by its path (e.g. `potato/ham`)
found nothing. It also gave the path tokens made-up offsets instead of
their position in the path.

The filter is replaced by a tokenizer that emits the raw path suffixes
starting at each segment and word (`potato/ham.md`, `ham.md`). Paths
below the root now match too, as do names containing `-` or spaces and
dotfiles. An exact file name also ranks above files inside a directory
with the same name.

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-09-24 07:57:42 +00:00

64 lines
1.8 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package bleve
import (
"testing"
"time"
"gitea.dev/models/db"
"gitea.dev/modules/indexer/code/internal"
inner_bleve "gitea.dev/modules/indexer/internal/bleve"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestBleveIndexerTokenFilter(t *testing.T) {
dir := t.TempDir()
indexer := NewIndexer(dir)
defer indexer.Close()
_, err := indexer.Init(t.Context())
require.NoError(t, err)
batch := inner_bleve.NewFlushingBatch(indexer.inner.Indexer, maxBatchSize)
batch.Index("2", &RepoIndexerData{RepoID: 2, Filename: ".sub-dir/.sub-filename", Content: "mDNS.port2=12345", UpdatedAt: time.Now()})
batch.Flush()
testCases := []struct {
keyword string
expectedIDs []int64
}{
{keyword: "12345", expectedIDs: []int64{2}},
{keyword: "DNS", expectedIDs: []int64{}},
{keyword: "mdns", expectedIDs: []int64{2}},
{keyword: "port", expectedIDs: []int64{2}},
{keyword: "port2", expectedIDs: []int64{2}},
{keyword: ".sub-dir", expectedIDs: []int64{2}},
{keyword: "sub-file", expectedIDs: []int64{2}}, // prefix matching? not sure whether this behavior is wanted
{keyword: "filename", expectedIDs: []int64{2}},
{keyword: "name", expectedIDs: []int64{}},
}
for _, testCase := range testCases {
t.Run(testCase.keyword, func(t *testing.T) {
_, results, _, err := indexer.Search(t.Context(), &internal.SearchOptions{
Paginator: &db.ListOptions{Page: 1, PageSize: 1},
Keyword: testCase.keyword,
})
require.NoError(t, err)
assert.ElementsMatch(t, testCase.expectedIDs, searchResultIDs(results))
})
}
}
func searchResultIDs(result []*internal.SearchResult) []int64 {
ids := make([]int64, 0, len(result))
for _, hit := range result {
ids = append(ids, hit.RepoID)
}
return ids
}