192 lines
5.0 KiB
Go
192 lines
5.0 KiB
Go
|
package repository
|
|||
|
|
|||
|
import (
|
|||
|
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain"
|
|||
|
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
|
|||
|
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
|
|||
|
mgo "code.30cm.net/digimon/library-go/mongo"
|
|||
|
"context"
|
|||
|
"errors"
|
|||
|
|
|||
|
"time"
|
|||
|
|
|||
|
"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"
|
|||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|||
|
)
|
|||
|
|
|||
|
type CategoryRepositoryParam struct {
|
|||
|
Conf *mgo.Conf
|
|||
|
CacheConf cache.CacheConf
|
|||
|
DBOpts []mon.Option
|
|||
|
CacheOpts []cache.Option
|
|||
|
}
|
|||
|
|
|||
|
type CategoryRepository struct {
|
|||
|
DB mgo.DocumentDBWithCacheUseCase
|
|||
|
}
|
|||
|
|
|||
|
func MustCategoryRepository(param CategoryRepositoryParam) repository.CategoryRepository {
|
|||
|
e := entity.Category{}
|
|||
|
|
|||
|
documentDB, err := mgo.MustDocumentDBWithCache(
|
|||
|
param.Conf,
|
|||
|
e.CollectionName(),
|
|||
|
param.CacheConf,
|
|||
|
param.DBOpts,
|
|||
|
param.CacheOpts,
|
|||
|
)
|
|||
|
if err != nil {
|
|||
|
panic(err)
|
|||
|
}
|
|||
|
|
|||
|
return &CategoryRepository{
|
|||
|
DB: documentDB,
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func (repo *CategoryRepository) IsCategoryExists(ctx context.Context, ids []string) []string {
|
|||
|
// 將傳入的 string id 轉換為 ObjectID
|
|||
|
objectIDs := make([]primitive.ObjectID, 0, len(ids))
|
|||
|
for _, id := range ids {
|
|||
|
objID, err := primitive.ObjectIDFromHex(id)
|
|||
|
if err == nil { // 如果轉換失敗,忽略該 id
|
|||
|
objectIDs = append(objectIDs, objID)
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 查詢存在的標籤
|
|||
|
filter := bson.M{"_id": bson.M{"$in": objectIDs}}
|
|||
|
// find 並沒有快取要快取要去其他地方做
|
|||
|
opts := options.Find().SetProjection(bson.M{"_id": 1}) // 只返回 _id 欄位
|
|||
|
// 執行查詢並獲取結果
|
|||
|
var category []*entity.Category
|
|||
|
err := repo.DB.GetClient().Find(ctx, &category, filter, opts)
|
|||
|
if err != nil {
|
|||
|
return []string{}
|
|||
|
}
|
|||
|
|
|||
|
// 將存在的標籤ID轉換回 string,並加入結果列表
|
|||
|
existingIDs := make([]string, 0, len(category))
|
|||
|
for _, item := range category {
|
|||
|
existingIDs = append(existingIDs, item.ID.Hex())
|
|||
|
}
|
|||
|
|
|||
|
return existingIDs
|
|||
|
}
|
|||
|
|
|||
|
func (repo *CategoryRepository) Insert(ctx context.Context, data *entity.Category) error {
|
|||
|
now := time.Now().UTC().UnixNano()
|
|||
|
if data.ID.IsZero() {
|
|||
|
data.ID = primitive.NewObjectID()
|
|||
|
data.CreatedAt = now
|
|||
|
data.UpdatedAt = now
|
|||
|
}
|
|||
|
|
|||
|
_, err := repo.DB.GetClient().InsertOne(ctx, data)
|
|||
|
|
|||
|
return err
|
|||
|
}
|
|||
|
|
|||
|
func (repo *CategoryRepository) FindOneByID(ctx context.Context, id string) (*entity.Category, error) {
|
|||
|
oid, err := primitive.ObjectIDFromHex(id)
|
|||
|
if err != nil {
|
|||
|
return nil, ErrInvalidObjectID
|
|||
|
}
|
|||
|
|
|||
|
var data entity.Category
|
|||
|
rk := domain.GetCategoryRedisKey(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 *CategoryRepository) Update(ctx context.Context, id string, data *entity.Category) (*mongo.UpdateResult, error) {
|
|||
|
oid, err := primitive.ObjectIDFromHex(id)
|
|||
|
if err != nil {
|
|||
|
return nil, ErrInvalidObjectID
|
|||
|
}
|
|||
|
|
|||
|
updateFields := bson.M{}
|
|||
|
if data.Name != "" {
|
|||
|
updateFields["name"] = data.Name
|
|||
|
}
|
|||
|
|
|||
|
updateFields["updated_at"] = time.Now().UTC().UnixNano()
|
|||
|
|
|||
|
// 構建查找條件
|
|||
|
filter := bson.M{"_id": oid}
|
|||
|
update := bson.M{"$set": updateFields}
|
|||
|
opt := options.Update().SetUpsert(false)
|
|||
|
|
|||
|
rk := domain.GetCategoryRedisKey(id)
|
|||
|
res, err := repo.DB.UpdateOne(ctx, rk, filter, update, opt)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
// 檢查更新結果,若沒有匹配的文檔,則返回錯誤
|
|||
|
if res.MatchedCount == 0 {
|
|||
|
return nil, ErrNotFound // 自定義的錯誤表示未找到記錄
|
|||
|
}
|
|||
|
|
|||
|
return res, err
|
|||
|
}
|
|||
|
|
|||
|
func (repo *CategoryRepository) Delete(ctx context.Context, id string) (int64, error) {
|
|||
|
oid, err := primitive.ObjectIDFromHex(id)
|
|||
|
if err != nil {
|
|||
|
return 0, ErrInvalidObjectID
|
|||
|
}
|
|||
|
rk := domain.GetCategoryRedisKey(id)
|
|||
|
res, err := repo.DB.DeleteOne(ctx, rk, bson.M{"_id": oid})
|
|||
|
|
|||
|
return res, err
|
|||
|
}
|
|||
|
|
|||
|
func (repo *CategoryRepository) ListCategory(ctx context.Context, params *repository.CategoryQueryParams) ([]*entity.Category, int64, error) {
|
|||
|
// TODO 有需要列表快取實在取列表快取
|
|||
|
// 構建查詢過濾器
|
|||
|
filter := bson.M{}
|
|||
|
if len(params.ID) > 0 {
|
|||
|
objectIDs := make([]primitive.ObjectID, 0, len(params.ID))
|
|||
|
for _, id := range params.ID {
|
|||
|
objID, err := primitive.ObjectIDFromHex(id)
|
|||
|
if err != nil {
|
|||
|
continue
|
|||
|
}
|
|||
|
objectIDs = append(objectIDs, objID)
|
|||
|
}
|
|||
|
filter["_id"] = bson.M{"$in": objectIDs}
|
|||
|
}
|
|||
|
|
|||
|
// 設置排序選項
|
|||
|
opts := options.Find().SetSkip((params.PageIndex - 1) * params.PageSize).SetLimit(params.PageSize)
|
|||
|
opts.SetSort(bson.D{{Key: "created_at", Value: -1}})
|
|||
|
|
|||
|
// 查詢符合條件的總數
|
|||
|
count, err := repo.DB.GetClient().CountDocuments(ctx, filter)
|
|||
|
if err != nil {
|
|||
|
return nil, 0, err
|
|||
|
}
|
|||
|
|
|||
|
// 執行查詢並獲取結果
|
|||
|
var category []*entity.Category
|
|||
|
err = repo.DB.GetClient().Find(ctx, &category, filter, opts)
|
|||
|
if err != nil {
|
|||
|
return nil, 0, err
|
|||
|
}
|
|||
|
|
|||
|
return category, count, nil
|
|||
|
}
|