package model import ( "context" "fmt" "permission/reborn-mongo/domain/entity" "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/monc" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) var _ RoleModel = (*customRoleModel)(nil) type ( // RoleModel go-zero model 介面 RoleModel interface { Insert(ctx context.Context, data *entity.Role) error FindOne(ctx context.Context, id primitive.ObjectID) (*entity.Role, error) FindOneByUID(ctx context.Context, uid string) (*entity.Role, error) FindMany(ctx context.Context, filter bson.M, opts ...*options.FindOptions) ([]*entity.Role, error) Update(ctx context.Context, data *entity.Role) error Delete(ctx context.Context, id primitive.ObjectID) error Count(ctx context.Context, filter bson.M) (int64, error) } customRoleModel struct { *monc.Model } ) // NewRoleModel 建立 Role Model (帶 cache) func NewRoleModel(url, db, collection string, c cache.CacheConf) RoleModel { return &customRoleModel{ Model: monc.MustNewModel(url, db, collection, c), } } func (m *customRoleModel) Insert(ctx context.Context, data *entity.Role) error { if data.ID.IsZero() { data.ID = primitive.NewObjectID() } data.TimeStamp = entity.NewTimeStamp() key := roleIDKey(data.ID) _, err := m.InsertOneNoCache(ctx, key, data) return err } func (m *customRoleModel) FindOne(ctx context.Context, id primitive.ObjectID) (*entity.Role, error) { var data entity.Role key := roleIDKey(id) err := m.FindOne(ctx, key, &data, func() (interface{}, error) { // 從 MongoDB 查詢 err := m.Model.FindOne(ctx, &data, bson.M{"_id": id, "status": bson.M{"$ne": entity.StatusDeleted}}) if err != nil { return nil, err } return &data, nil }) if err != nil { return nil, err } return &data, nil } func (m *customRoleModel) FindOneByUID(ctx context.Context, uid string) (*entity.Role, error) { var data entity.Role key := roleUIDKey(uid) err := m.Model.FindOneNoCache(ctx, &data, bson.M{ "uid": uid, "status": bson.M{"$ne": entity.StatusDeleted}, }) if err != nil { if err == monc.ErrNotFound { return nil, ErrNotFound } return nil, err } return &data, nil } func (m *customRoleModel) FindMany(ctx context.Context, filter bson.M, opts ...*options.FindOptions) ([]*entity.Role, error) { // 確保不查詢已刪除的 if filter == nil { filter = bson.M{} } filter["status"] = bson.M{"$ne": entity.StatusDeleted} var data []*entity.Role err := m.Model.Find(ctx, &data, filter, opts...) if err != nil { return nil, err } return data, nil } func (m *customRoleModel) Update(ctx context.Context, data *entity.Role) error { data.UpdateTimestamp() key := roleIDKey(data.ID) _, err := m.Model.ReplaceOneNoCache(ctx, key, bson.M{"_id": data.ID}, data) return err } func (m *customRoleModel) Delete(ctx context.Context, id primitive.ObjectID) error { key := roleIDKey(id) // 軟刪除 _, err := m.Model.UpdateOneNoCache(ctx, key, bson.M{"_id": id}, bson.M{ "$set": bson.M{ "status": entity.StatusDeleted, "update_time": entity.NewTimeStamp().UpdateTime, }, }) return err } func (m *customRoleModel) Count(ctx context.Context, filter bson.M) (int64, error) { if filter == nil { filter = bson.M{} } filter["status"] = bson.M{"$ne": entity.StatusDeleted} return m.Model.CountDocuments(ctx, filter) } // Cache keys func roleIDKey(id primitive.ObjectID) string { return fmt.Sprintf("cache:role:id:%s", id.Hex()) } func roleUIDKey(uid string) string { return fmt.Sprintf("cache:role:uid:%s", uid) } var ErrNotFound = mongo.ErrNoDocuments