mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-06-23 01:20:50 +00:00
An attempt at solving #7956. This (and rebuilding the index) seems enough to ensure the issue *appears* among the results. However, I couldn't figure out from [bleve docs](https://github.com/blevesearch/bleve/blob/master/docs/scoring.md) how to affect the scoring based on specific fields, or whether that is possible at all. Disclaimer: I've never written Go before, sorry 😅 take it as a quick PoC more than anything. ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [x] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [x] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. <!--start release-notes-assistant--> ## Release notes <!--URL:https://codeberg.org/forgejo/forgejo--> - Features - [PR](https://codeberg.org/forgejo/forgejo/pulls/7968): <!--number 7968 --><!--line 0 --><!--description QWRkIGlzc3VlIG51bWJlciB0byB0aGUgc2VhcmNoIGluZGV4LCByYW5rIG51bWJlciBhbmQgdGl0bGUgbWF0Y2hlcyBoaWdoZXIgKCM3OTU2KQ==-->Add issue number to the search index, rank number and title matches higher (#7956)<!--description--> <!--end release-notes-assistant--> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7968 Reviewed-by: Shiny Nematoda <snematoda@noreply.codeberg.org> Co-authored-by: Danko Aleksejevs <danko@very.lv> Co-committed-by: Danko Aleksejevs <danko@very.lv>
119 lines
3.4 KiB
Go
119 lines
3.4 KiB
Go
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
|
|
"forgejo.org/models/db"
|
|
issue_model "forgejo.org/models/issues"
|
|
indexer_internal "forgejo.org/modules/indexer/internal"
|
|
inner_db "forgejo.org/modules/indexer/internal/db"
|
|
"forgejo.org/modules/indexer/issues/internal"
|
|
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
var _ internal.Indexer = &Indexer{}
|
|
|
|
// Indexer implements Indexer interface to use database's like search
|
|
type Indexer struct {
|
|
indexer_internal.Indexer
|
|
}
|
|
|
|
func NewIndexer() *Indexer {
|
|
return &Indexer{
|
|
Indexer: &inner_db.Indexer{},
|
|
}
|
|
}
|
|
|
|
// Index dummy function
|
|
func (i *Indexer) Index(_ context.Context, _ ...*internal.IndexerData) error {
|
|
return nil
|
|
}
|
|
|
|
// Delete dummy function
|
|
func (i *Indexer) Delete(_ context.Context, _ ...int64) error {
|
|
return nil
|
|
}
|
|
|
|
// Search searches for issues
|
|
func (i *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (*internal.SearchResult, error) {
|
|
// FIXME: I tried to avoid importing models here, but it seems to be impossible.
|
|
// We can provide a function to register the search function, so models/issues can register it.
|
|
// So models/issues will import modules/indexer/issues, it's OK because it's by design.
|
|
// But modules/indexer/issues has already imported models/issues to do UpdateRepoIndexer and UpdateIssueIndexer.
|
|
// And to avoid circular import, we have to move the functions to another package.
|
|
// I believe it should be services/indexer, sounds great!
|
|
// But the two functions are used in modules/notification/indexer, that means we will import services/indexer in modules/notification/indexer.
|
|
// So that's the root problem:
|
|
// The notification is defined in modules, but it's using lots of things should be in services.
|
|
|
|
cond := builder.NewCond()
|
|
|
|
if options.Keyword != "" {
|
|
repoCond := builder.In("repo_id", options.RepoIDs)
|
|
if len(options.RepoIDs) == 1 {
|
|
repoCond = builder.Eq{"repo_id": options.RepoIDs[0]}
|
|
}
|
|
subQuery := builder.Select("id").From("issue").Where(repoCond)
|
|
|
|
cond = builder.Or(
|
|
db.BuildCaseInsensitiveLike("issue.name", options.Keyword),
|
|
db.BuildCaseInsensitiveLike("issue.content", options.Keyword),
|
|
builder.In("issue.id", builder.Select("issue_id").
|
|
From("comment").
|
|
Where(builder.And(
|
|
builder.Eq{"type": issue_model.CommentTypeComment},
|
|
builder.In("issue_id", subQuery),
|
|
db.BuildCaseInsensitiveLike("content", options.Keyword),
|
|
)),
|
|
),
|
|
)
|
|
|
|
term := options.Keyword
|
|
if term[0] == '#' || term[0] == '!' {
|
|
term = term[1:]
|
|
}
|
|
if issueID, err := strconv.ParseInt(term, 10, 64); err == nil {
|
|
cond = builder.Or(
|
|
builder.Eq{"`index`": issueID},
|
|
cond,
|
|
)
|
|
}
|
|
}
|
|
|
|
opt, err := ToDBOptions(ctx, options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// If pagesize == 0, return total count only. It's a special case for search count.
|
|
if options.Paginator != nil && options.Paginator.PageSize == 0 {
|
|
total, err := issue_model.CountIssues(ctx, opt, cond)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &internal.SearchResult{
|
|
Total: total,
|
|
}, nil
|
|
}
|
|
|
|
ids, total, err := issue_model.IssueIDs(ctx, opt, cond)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
hits := make([]internal.Match, 0, len(ids))
|
|
for _, id := range ids {
|
|
hits = append(hits, internal.Match{
|
|
ID: id,
|
|
})
|
|
}
|
|
return &internal.SearchResult{
|
|
Total: total,
|
|
Hits: hits,
|
|
}, nil
|
|
}
|