11package db
22
33import (
4+ "fmt"
45 "github.com/alist-org/alist/v3/internal/model"
56 "github.com/pkg/errors"
67 "gorm.io/gorm"
8+ "gorm.io/gorm/clause"
79 "time"
810)
911
1012// GetLabelIds Get all label_ids from database order by file_name
1113func GetLabelIds (userId uint , fileName string ) ([]uint , error ) {
12- labelFileBinDingDB := db .Model (& model.LabelFileBinDing {})
14+ //fmt.Printf(">>> [GetLabelIds] userId: %d, fileName: %s\n", userId, fileName)
15+ labelFileBinDingDB := db .Model (& model.LabelFileBinding {})
1316 var labelIds []uint
1417 if err := labelFileBinDingDB .Where ("file_name = ?" , fileName ).Where ("user_id = ?" , userId ).Pluck ("label_id" , & labelIds ).Error ; err != nil {
1518 return nil , errors .WithStack (err )
@@ -18,7 +21,7 @@ func GetLabelIds(userId uint, fileName string) ([]uint, error) {
1821}
1922
2023func CreateLabelFileBinDing (fileName string , labelId , userId uint ) error {
21- var labelFileBinDing model.LabelFileBinDing
24+ var labelFileBinDing model.LabelFileBinding
2225 labelFileBinDing .UserId = userId
2326 labelFileBinDing .LabelId = labelId
2427 labelFileBinDing .FileName = fileName
@@ -32,25 +35,158 @@ func CreateLabelFileBinDing(fileName string, labelId, userId uint) error {
3235
3336// GetLabelFileBinDingByLabelIdExists Get Label by label_id, used to del label usually
3437func GetLabelFileBinDingByLabelIdExists (labelId , userId uint ) bool {
35- var labelFileBinDing model.LabelFileBinDing
38+ var labelFileBinDing model.LabelFileBinding
3639 result := db .Where ("label_id = ?" , labelId ).Where ("user_id = ?" , userId ).First (& labelFileBinDing )
3740 exists := ! errors .Is (result .Error , gorm .ErrRecordNotFound )
3841 return exists
3942}
4043
4144// DelLabelFileBinDingByFileName used to del usually
4245func DelLabelFileBinDingByFileName (userId uint , fileName string ) error {
43- return errors .WithStack (db .Where ("file_name = ?" , fileName ).Where ("user_id = ?" , userId ).Delete (model.LabelFileBinDing {}).Error )
46+ return errors .WithStack (db .Where ("file_name = ?" , fileName ).Where ("user_id = ?" , userId ).Delete (model.LabelFileBinding {}).Error )
4447}
4548
4649// DelLabelFileBinDingById used to del usually
4750func DelLabelFileBinDingById (labelId , userId uint , fileName string ) error {
48- return errors .WithStack (db .Where ("label_id = ?" , labelId ).Where ("file_name = ?" , fileName ).Where ("user_id = ?" , userId ).Delete (model.LabelFileBinDing {}).Error )
51+ return errors .WithStack (db .Where ("label_id = ?" , labelId ).Where ("file_name = ?" , fileName ).Where ("user_id = ?" , userId ).Delete (model.LabelFileBinding {}).Error )
4952}
5053
51- func GetLabelFileBinDingByLabelId (labelIds []uint , userId uint ) (result []model.LabelFileBinDing , err error ) {
54+ func GetLabelFileBinDingByLabelId (labelIds []uint , userId uint ) (result []model.LabelFileBinding , err error ) {
5255 if err := db .Where ("label_id in (?)" , labelIds ).Where ("user_id = ?" , userId ).Find (& result ).Error ; err != nil {
5356 return nil , errors .WithStack (err )
5457 }
5558 return result , nil
5659}
60+
61+ func GetLabelBindingsByFileNamesPublic (fileNames []string ) (map [string ][]uint , error ) {
62+ var binds []model.LabelFileBinding
63+ if err := db .Where ("file_name IN ?" , fileNames ).Find (& binds ).Error ; err != nil {
64+ return nil , errors .WithStack (err )
65+ }
66+ out := make (map [string ][]uint , len (fileNames ))
67+ seen := make (map [string ]struct {}, len (binds ))
68+ for _ , b := range binds {
69+ key := fmt .Sprintf ("%s-%d" , b .FileName , b .LabelId )
70+ if _ , ok := seen [key ]; ok {
71+ continue
72+ }
73+ seen [key ] = struct {}{}
74+ out [b .FileName ] = append (out [b .FileName ], b .LabelId )
75+ }
76+ return out , nil
77+ }
78+
79+ func GetLabelsByFileNamesPublic (fileNames []string ) (map [string ][]model.Label , error ) {
80+ bindMap , err := GetLabelBindingsByFileNamesPublic (fileNames )
81+ if err != nil {
82+ return nil , err
83+ }
84+
85+ idSet := make (map [uint ]struct {})
86+ for _ , ids := range bindMap {
87+ for _ , id := range ids {
88+ idSet [id ] = struct {}{}
89+ }
90+ }
91+ if len (idSet ) == 0 {
92+ return make (map [string ][]model.Label , 0 ), nil
93+ }
94+ allIDs := make ([]uint , 0 , len (idSet ))
95+ for id := range idSet {
96+ allIDs = append (allIDs , id )
97+ }
98+ labels , err := GetLabelByIds (allIDs ) // 你已有的函数
99+ if err != nil {
100+ return nil , err
101+ }
102+
103+ labelByID := make (map [uint ]model.Label , len (labels ))
104+ for _ , l := range labels {
105+ labelByID [l .ID ] = l
106+ }
107+
108+ out := make (map [string ][]model.Label , len (bindMap ))
109+ for fname , ids := range bindMap {
110+ for _ , id := range ids {
111+ if lab , ok := labelByID [id ]; ok {
112+ out [fname ] = append (out [fname ], lab )
113+ }
114+ }
115+ }
116+ return out , nil
117+ }
118+
119+ func ListLabelFileBinDing (userId uint , labelIDs []uint , fileName string , page , pageSize int ) ([]model.LabelFileBinding , int64 , error ) {
120+ q := db .Model (& model.LabelFileBinding {}).Where ("user_id = ?" , userId )
121+
122+ if len (labelIDs ) > 0 {
123+ q = q .Where ("label_id IN ?" , labelIDs )
124+ }
125+ if fileName != "" {
126+ q = q .Where ("file_name LIKE ?" , "%" + fileName + "%" )
127+ }
128+
129+ var total int64
130+ if err := q .Count (& total ).Error ; err != nil {
131+ return nil , 0 , errors .WithStack (err )
132+ }
133+
134+ var rows []model.LabelFileBinding
135+ if err := q .
136+ Order ("id DESC" ).
137+ Offset ((page - 1 ) * pageSize ).
138+ Limit (pageSize ).
139+ Find (& rows ).Error ; err != nil {
140+ return nil , 0 , errors .WithStack (err )
141+ }
142+ return rows , total , nil
143+ }
144+
145+ func RestoreLabelFileBindings (bindings []model.LabelFileBinding , keepIDs bool , override bool ) error {
146+ if len (bindings ) == 0 {
147+ return nil
148+ }
149+ tx := db .Begin ()
150+
151+ if override {
152+ type key struct {
153+ uid uint
154+ name string
155+ }
156+ toDel := make (map [key ]struct {}, len (bindings ))
157+ for i := range bindings {
158+ k := key {uid : bindings [i ].UserId , name : bindings [i ].FileName }
159+ toDel [k ] = struct {}{}
160+ }
161+ for k := range toDel {
162+ if err := tx .Where ("user_id = ? AND file_name = ?" , k .uid , k .name ).
163+ Delete (& model.LabelFileBinding {}).Error ; err != nil {
164+ tx .Rollback ()
165+ return errors .WithStack (err )
166+ }
167+ }
168+ }
169+
170+ for i := range bindings {
171+ b := bindings [i ]
172+ if ! keepIDs {
173+ b .ID = 0
174+ }
175+ if b .CreateTime .IsZero () {
176+ b .CreateTime = time .Now ()
177+ }
178+ if override {
179+ if err := tx .Create (& b ).Error ; err != nil {
180+ tx .Rollback ()
181+ return errors .WithStack (err )
182+ }
183+ } else {
184+ if err := tx .Clauses (clause.OnConflict {DoNothing : true }).Create (& b ).Error ; err != nil {
185+ tx .Rollback ()
186+ return errors .WithStack (err )
187+ }
188+ }
189+ }
190+
191+ return errors .WithStack (tx .Commit ().Error )
192+ }
0 commit comments