From 179d285564708feba4b1cb182008b83fea5357d9 Mon Sep 17 00:00:00 2001 From: BoYanZh Date: Mon, 12 Dec 2022 20:20:01 +0800 Subject: [PATCH] feat: optimize database search (#2687) * feat: remove index on `SearchNode.Name` As we do not use s% on name column, index there does not work * fix: init index after init data Or on the first run, it will log 'init index error: readObjectStart: expect { or n, but found , error found in #0 byte of ...||..., bigger context ...||...' * fix: match parent more precisely It will match `/a/bc` if we search in `/a/b` originally. But it is not backward compatible by adding a suffix `/` to all the data in parent field --- cmd/common.go | 2 +- internal/db/searchnode.go | 16 ++++++++++------ internal/model/search.go | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cmd/common.go b/cmd/common.go index 1d8f5959..c60d8731 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -15,8 +15,8 @@ func Init() { bootstrap.InitConfig() bootstrap.Log() bootstrap.InitDB() - bootstrap.InitIndex() data.InitData() + bootstrap.InitIndex() } var pid = -1 diff --git a/internal/db/searchnode.go b/internal/db/searchnode.go index ac75f33b..e121f0df 100644 --- a/internal/db/searchnode.go +++ b/internal/db/searchnode.go @@ -8,8 +8,16 @@ import ( "github.com/alist-org/alist/v3/internal/model" "github.com/alist-org/alist/v3/pkg/utils" "github.com/pkg/errors" + "gorm.io/gorm" ) +func whereInParent(parent string) *gorm.DB { + return db.Where(fmt.Sprintf("%s LIKE ?", columnName("parent")), + fmt.Sprintf("%s/%%", parent)). + Or(fmt.Sprintf("%s = ?", columnName("parent")), + fmt.Sprintf("%s%%", parent)) +} + func CreateSearchNode(node *model.SearchNode) error { return db.Create(node).Error } @@ -19,9 +27,7 @@ func BatchCreateSearchNodes(nodes *[]model.SearchNode) error { } func DeleteSearchNodesByParent(prefix string) error { - err := db.Where(fmt.Sprintf("%s LIKE ?", - columnName("parent")), fmt.Sprintf("%s%%", prefix)). - Delete(&model.SearchNode{}).Error + err := db.Where(whereInParent(prefix)).Delete(&model.SearchNode{}).Error if err != nil { return err } @@ -51,9 +57,7 @@ func SearchNode(req model.SearchReq) ([]model.SearchNode, int64, error) { fmt.Sprintf("%s LIKE ?", columnName("name")), fmt.Sprintf("%%%s%%", keyword)) } - searchDB := db.Model(&model.SearchNode{}).Where( - fmt.Sprintf("%s LIKE ?", columnName("parent")), - fmt.Sprintf("%s%%", req.Parent)).Where(keywordsClause) + searchDB := db.Model(&model.SearchNode{}).Where(whereInParent(req.Parent)).Where(keywordsClause) var count int64 if err := searchDB.Count(&count).Error; err != nil { return nil, 0, errors.Wrapf(err, "failed get users count") diff --git a/internal/model/search.go b/internal/model/search.go index 409fb3ee..ddcaee28 100644 --- a/internal/model/search.go +++ b/internal/model/search.go @@ -20,7 +20,7 @@ type SearchReq struct { type SearchNode struct { Parent string `json:"parent" gorm:"index"` - Name string `json:"name" gorm:"index"` + Name string `json:"name"` IsDir bool `json:"is_dir"` Size int64 `json:"size"` }