diff --git a/server/dao/tag.go b/server/dao/tag.go index 5dc8292..77a4df7 100644 --- a/server/dao/tag.go +++ b/server/dao/tag.go @@ -140,3 +140,27 @@ func RemoveTagAliasOf(tagID uint) error { }, }).Update("alias_of", nil).Error } + +// ClearUnusedTags removes tags that are not associated with any resources. +func ClearUnusedTags() error { + var tags []model.Tag + if err := db.Where("alias_of IS NULL").Find(&tags).Error; err != nil { + return err + } + for _, tag := range tags { + var count int64 + if err := db. + Model(&model.Resource{}). + Where("id IN (SELECT resource_id FROM resource_tags WHERE tag_id = ?)", tag.ID). + Count(&count).Error; err != nil { + return err + } + if count == 0 { + // Use hard delete to remove the tag to ensure the tag can be re-created later + if err := db.Unscoped().Delete(&tag).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + return err + } + } + } + return nil +} diff --git a/server/service/tag.go b/server/service/tag.go index 41c2921..a8d0b49 100644 --- a/server/service/tag.go +++ b/server/service/tag.go @@ -6,8 +6,24 @@ import ( "nysoure/server/model" "slices" "strings" + "time" ) +func init() { + // Start a goroutine to delete unused tags every hour + go func() { + // Wait for 1 minute to ensure the database is ready + time.Sleep(time.Minute) + for { + err := dao.ClearUnusedTags() + if err != nil { + log.Errorf("Failed to clear unused tags: %v", err) + } + time.Sleep(time.Hour) + } + }() +} + func CreateTag(uid uint, name string) (*model.TagView, error) { canUpload, err := checkUserCanUpload(uid) if err != nil {