package repository import ( "app-cloudep-member-server/pkg/domain" "app-cloudep-member-server/pkg/domain/entity" "app-cloudep-member-server/pkg/domain/repository" "context" "errors" "time" mgo "code.30cm.net/digimon/library-go/mongo" "github.com/zeromicro/go-zero/core/stores/cache" "github.com/zeromicro/go-zero/core/stores/mon" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" ) type AccountRepositoryParam struct { Conf *mgo.Conf CacheConf cache.CacheConf DbOpts []mon.Option CacheOpts []cache.Option } type AccountRepository struct { DB mgo.DocumentDBWithCacheUseCase } func NewAccountRepository(param AccountRepositoryParam) repository.AccountRepository { e := entity.Account{} documentDB, err := mgo.MustDocumentDBWithCache( param.Conf, e.CollectionName(), param.CacheConf, param.DbOpts, param.CacheOpts, ) if err != nil { panic(err) } return &AccountRepository{ DB: documentDB, } } func (repo *AccountRepository) Insert(ctx context.Context, data *entity.Account) error { if data.ID.IsZero() { now := time.Now().UTC().UnixNano() data.ID = primitive.NewObjectID() data.CreateAt = &now data.UpdateAt = &now } rk := domain.GetAccountRedisKey(data.ID.Hex()) _, err := repo.DB.InsertOne(ctx, rk, data) return err } func (repo *AccountRepository) FindOne(ctx context.Context, id string) (*entity.Account, error) { oid, err := primitive.ObjectIDFromHex(id) if err != nil { return nil, ErrInvalidObjectID } var data entity.Account rk := domain.GetAccountRedisKey(id) err = repo.DB.FindOne(ctx, rk, &data, bson.M{"_id": oid}) switch { case err == nil: return &data, nil case errors.Is(err, mon.ErrNotFound): return nil, ErrNotFound default: return nil, err } } func (repo *AccountRepository) Update(ctx context.Context, data *entity.Account) (*mongo.UpdateResult, error) { now := time.Now().UTC().UnixNano() data.UpdateAt = &now rk := domain.GetAccountRedisKey(data.ID.Hex()) res, err := repo.DB.UpdateOne(ctx, rk, bson.M{"_id": data.ID}, bson.M{"$set": data}) return res, err } func (repo *AccountRepository) Delete(ctx context.Context, id string) (int64, error) { oid, err := primitive.ObjectIDFromHex(id) if err != nil { return 0, ErrInvalidObjectID } rk := domain.GetAccountRedisKey(id) return repo.DB.DeleteOne(ctx, rk, bson.M{"_id": oid}) } func (repo *AccountRepository) FindOneByAccount(ctx context.Context, loginID string) (*entity.Account, error) { // todo: 之後需要同步快取 var data entity.Account err := repo.DB.GetClient().FindOne(ctx, &data, bson.M{"login_id": loginID}) switch { case err == nil: return &data, nil case errors.Is(err, mon.ErrNotFound): return nil, ErrNotFound default: return nil, err } } func (repo *AccountRepository) UpdateTokenByLoginID(ctx context.Context, account string, token string) error { // todo: 之後需要同步快取 filter := bson.M{"login_id": account} update := bson.M{ "$set": bson.M{ "token": token, "update_at": time.Now().UTC().UnixNano(), }, } var data entity.Account err := repo.DB.GetClient().FindOne(ctx, &data, filter) if err != nil { return err } rk := domain.GetAccountRedisKey(data.ID.Hex()) modify, err := repo.DB.UpdateOne(ctx, rk, bson.M{"_id": data.ID}, update) if err != nil { return err } if modify.MatchedCount == 0 { return ErrNotFound // 自定義的錯誤表示未找到記錄 } return nil } func (repo *AccountRepository) Index20241226001UP(ctx context.Context) (*mongo.Cursor, error) { // 等價於 db.account.createIndex({ "login_id": 1, "platform": 1}, {unique: true}) repo.DB.PopulateMultiIndex(ctx, []string{ "login_id", "platform", }, []int32{1, 1}, true) // 等價於 db.account.createIndex({"create_at": 1}) repo.DB.PopulateIndex(ctx, "create_at", 1, false) return repo.DB.GetClient().Indexes().List(ctx) }