From a3796aabdc711d8e99563bf0c0f50c03785816da Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Thu, 29 Aug 2024 22:49:42 +0800 Subject: [PATCH] add get inc or dec count --- generate/protobuf/tweeting.proto | 18 +++++- internal/domain/const.go | 2 +- .../logic/postservice/count_like_logic.go | 35 ++++++++-- .../inc_dec_like_dislike_count_logic.go | 64 +++++++++++++++++++ internal/logic/postservice/like_logic.go | 22 ++++--- internal/model/mongo/post_likes_model.go | 35 ++++++++-- internal/model/mongo/post_model.go | 38 +++++++++++ .../server/postservice/post_service_server.go | 8 ++- 8 files changed, 198 insertions(+), 24 deletions(-) create mode 100644 internal/logic/postservice/inc_dec_like_dislike_count_logic.go diff --git a/generate/protobuf/tweeting.proto b/generate/protobuf/tweeting.proto index 8a0b6f3..e760ba9 100644 --- a/generate/protobuf/tweeting.proto +++ b/generate/protobuf/tweeting.proto @@ -130,7 +130,7 @@ message LikeCountReq { // 讚/不讚數量回應 message LikeCountResp { - string count = 1; // 總共按讚數量 + int64 count = 1; // 總共按讚數量 } // 評論貼文的請求 @@ -174,6 +174,18 @@ message UpdateCommentReq { string content = 2; // 更新後的評論內容 } +message PostReactionActionResp { + string PostID =1; // 貼文的 ID + int64 reaction_type = 2; // 用戶的反應類型,可能是讚或不讚 + bool is_increment = 3; // 表示是否增加(true 表示增加,false 表示減少) +} + +message IncDecLikeDislikeCountReq { + string PostID =1; // 貼文的 ID + int64 reaction_type = 2; // 用戶的反應類型,可能是讚或不讚 + bool is_increment = 3; // 表示是否增加(true 表示增加,false 表示減少) +} + // 定義貼文服務 service PostService { // NewPost 新增貼文 @@ -184,9 +196,11 @@ service PostService { rpc UpdatePost(UpdatePostReq) returns (OKResp); // ListPosts 查詢貼文 rpc ListPosts(QueryPostsReq) returns (ListPostsResp); + // IncDecLikeDislikeCount 增減數量 + rpc IncDecLikeDislikeCount(IncDecLikeDislikeCountReq) returns (OKResp); // Like 點讚/取消讚 貼文 - rpc Like(LikeReq) returns (OKResp); + rpc Like(LikeReq) returns (PostReactionActionResp); // GetLikeStatus 取得讚/不讚狀態 rpc GetLikeStatus(GetLikeStatusReq) returns (GetLikeStatusResp); // LikeList 取得讚/不讚列表 diff --git a/internal/domain/const.go b/internal/domain/const.go index 6b58d8f..7329e83 100644 --- a/internal/domain/const.go +++ b/internal/domain/const.go @@ -14,7 +14,7 @@ const ( type LikeType int8 -func (l LikeType) ToInt32() int8 { +func (l LikeType) ToInt8() int8 { return int8(l) } diff --git a/internal/logic/postservice/count_like_logic.go b/internal/logic/postservice/count_like_logic.go index 4fb4e67..0000038 100644 --- a/internal/logic/postservice/count_like_logic.go +++ b/internal/logic/postservice/count_like_logic.go @@ -1,10 +1,11 @@ package postservicelogic import ( - "context" - "app-cloudep-tweeting-service/gen_result/pb/tweeting" + "app-cloudep-tweeting-service/internal/domain" "app-cloudep-tweeting-service/internal/svc" + ers "code.30cm.net/digimon/library-go/errs" + "context" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +24,35 @@ func NewCountLikeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CountLi } } +type countLikeReq struct { + PostID string `json:"post_id" validate:"required"` // 貼文的 ID + ReactionType domain.LikeType `json:"reaction_type" validate:"required,oneof=1 2"` // 用戶的反應類型,可能是讚或不讚 +} + // CountLike 取得讚/不讚數量 func (l *CountLikeLogic) CountLike(in *tweeting.LikeCountReq) (*tweeting.LikeCountResp, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&countLikeReq{ + PostID: in.GetTargetId(), + ReactionType: domain.LikeType(in.GetLikeType()), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } - return &tweeting.LikeCountResp{}, nil + count, err := l.svcCtx.PostLikeModel.Count(l.ctx, in.GetTargetId(), domain.LikeType(in.GetLikeType())) + if err != nil { + e := domain.PostMongoErrorL( + logx.WithContext(l.ctx), + []logx.LogField{ + {Key: "req", Value: in}, + {Key: "func", Value: "PostLikeModel.Count"}, + {Key: "err", Value: err}, + }, + "failed to count like or dislike").Wrap(err) + return nil, e + } + + return &tweeting.LikeCountResp{ + Count: count, + }, nil } diff --git a/internal/logic/postservice/inc_dec_like_dislike_count_logic.go b/internal/logic/postservice/inc_dec_like_dislike_count_logic.go new file mode 100644 index 0000000..3d08230 --- /dev/null +++ b/internal/logic/postservice/inc_dec_like_dislike_count_logic.go @@ -0,0 +1,64 @@ +package postservicelogic + +import ( + "app-cloudep-tweeting-service/internal/domain" + model "app-cloudep-tweeting-service/internal/model/mongo" + ers "code.30cm.net/digimon/library-go/errs" + "context" + + "app-cloudep-tweeting-service/gen_result/pb/tweeting" + "app-cloudep-tweeting-service/internal/svc" + + "github.com/zeromicro/go-zero/core/logx" +) + +type IncDecLikeDislikeCountLogic struct { + ctx context.Context + svcCtx *svc.ServiceContext + logx.Logger +} + +func NewIncDecLikeDislikeCountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *IncDecLikeDislikeCountLogic { + return &IncDecLikeDislikeCountLogic{ + ctx: ctx, + svcCtx: svcCtx, + Logger: logx.WithContext(ctx), + } +} + +type postReactionAction struct { + PostID string `json:"post_id" validate:"required"` // 貼文的 ID + ReactionType domain.LikeType `json:"reaction_type" validate:"required,oneof=1 2"` // 用戶的反應類型,可能是讚或不讚 + IsIncrement bool `json:"is_increment" validate:"required"` // 表示是否增加(true 表示增加,false 表示減少) +} + +// IncDecLikeDislikeCount 增減數量 +func (l *IncDecLikeDislikeCountLogic) IncDecLikeDislikeCount(in *tweeting.IncDecLikeDislikeCountReq) (*tweeting.OKResp, error) { + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&postReactionAction{ + PostID: in.GetPostID(), + ReactionType: domain.LikeType(in.GetReactionType()), + IsIncrement: in.GetIsIncrement(), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } + + err := l.svcCtx.PostModel.IncDecLikeDislikeCountLogic(l.ctx, &model.PostReactionAction{ + PostID: in.GetPostID(), + ReactionType: domain.LikeType(in.GetReactionType()), + IsIncrement: in.GetIsIncrement(), + }) + if err != nil { + e := domain.PostMongoErrorL( + logx.WithContext(l.ctx), + []logx.LogField{ + {Key: "req", Value: in}, + {Key: "func", Value: "PostModel.IncDecLikeDislikeCountLogic"}, + {Key: "err", Value: err}, + }, + "failed to inc like or dislike").Wrap(err) + return nil, e + } + + return &tweeting.OKResp{}, nil +} diff --git a/internal/logic/postservice/like_logic.go b/internal/logic/postservice/like_logic.go index 5c26126..6d211d8 100644 --- a/internal/logic/postservice/like_logic.go +++ b/internal/logic/postservice/like_logic.go @@ -27,23 +27,21 @@ func NewLikeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LikeLogic { } type likeReq struct { - Target string `json:"target" validate:"required"` - UID string `json:"uid" validate:"required"` - LikeType domain.LikeType `json:"like_type" validate:"required,oneof=1 2"` + Target string `json:"target" validate:"required"` + UID string `json:"uid" validate:"required"` } // Like 點讚/取消讚 貼文 -func (l *LikeLogic) Like(in *tweeting.LikeReq) (*tweeting.OKResp, error) { +func (l *LikeLogic) Like(in *tweeting.LikeReq) (*tweeting.PostReactionActionResp, error) { // 驗證資料 if err := l.svcCtx.Validate.ValidateAll(&likeReq{ - Target: in.TargetId, - UID: in.GetUid(), - LikeType: domain.LikeType(in.GetLikeType()), + Target: in.TargetId, + UID: in.GetUid(), }); err != nil { return nil, ers.InvalidFormat(err.Error()) } - err := l.svcCtx.PostLikeModel.LikeDislike(l.ctx, &model.PostLikes{ + likeResp, err := l.svcCtx.PostLikeModel.LikeDislike(l.ctx, &model.PostLikes{ TargetID: in.GetTargetId(), UID: in.GetUid(), Type: int8(in.GetLikeType()), @@ -60,5 +58,11 @@ func (l *LikeLogic) Like(in *tweeting.LikeReq) (*tweeting.OKResp, error) { return nil, e } - return &tweeting.OKResp{}, nil + // 將文章的數量增加或減少的功能,是業務邏輯,從外面再決定要不要丟MQ 後算,或是怎麼算 + + return &tweeting.PostReactionActionResp{ + PostID: likeResp.PostID, + ReactionType: int64(likeResp.ReactionType), + IsIncrement: likeResp.IsIncrement, + }, nil } diff --git a/internal/model/mongo/post_likes_model.go b/internal/model/mongo/post_likes_model.go index 87cf5aa..6a73f88 100644 --- a/internal/model/mongo/post_likes_model.go +++ b/internal/model/mongo/post_likes_model.go @@ -19,9 +19,16 @@ type ( // and implement the added methods in customPost_likesModel. Post_likesModel interface { post_likesModel - LikeDislike(ctx context.Context, postLike *PostLikes) error + LikeDislike(ctx context.Context, postLike *PostLikes) (*PostReactionAction, error) FindLikeUsers(ctx context.Context, param *QueryPostLikeReq) ([]*PostLikes, int64, error) FindUIDPostLikeStatus(ctx context.Context, param *QueryUIDPostLikeStatusReq) ([]UIDPostLikeStatusResp, error) + Count(ctx context.Context, target string, likeType domain.LikeType) (int64, error) + } + + PostReactionAction struct { + PostID string // 貼文的 ID + ReactionType domain.LikeType // 用戶的反應類型,可能是讚或不讚 + IsIncrement bool // 表示是否增加(true 表示增加,false 表示減少) } QueryPostLikeReq struct { @@ -55,7 +62,12 @@ func NewPost_likesModel(url, db, collection string) Post_likesModel { } } -func (m *defaultPost_likesModel) LikeDislike(ctx context.Context, postLike *PostLikes) error { +func (m *defaultPost_likesModel) LikeDislike(ctx context.Context, postLike *PostLikes) (*PostReactionAction, error) { + result := &PostReactionAction{ + PostID: postLike.TargetID, + ReactionType: domain.LikeType(postLike.Type), + } + // 使用 target_id、uid、type 來查詢資料是否存在 filter := bson.M{ "target_id": postLike.TargetID, @@ -69,23 +81,27 @@ func (m *defaultPost_likesModel) LikeDislike(ctx context.Context, postLike *Post if err == nil { // 資料存在,進行刪除操作 + result.IsIncrement = false _, err = m.conn.DeleteOne(ctx, filter) if err != nil { - return err // 刪除失敗 + return nil, err // 刪除失敗 } - return nil // 刪除成功 + + return result, nil // 刪除成功 } else if errors.Is(mongo.ErrNoDocuments, err) { // 資料不存在,進行插入操作 + result.IsIncrement = true postLike.ID = primitive.NewObjectID() // 設置新的 ObjectID postLike.CreateAt = time.Now().UTC().UnixNano() _, err = m.conn.InsertOne(ctx, postLike) if err != nil { - return err // 插入失敗 + return nil, err // 插入失敗 } - return nil // 插入成功 + + return result, nil // 插入成功 } else { // 其他錯誤 - return err + return nil, err } } @@ -171,3 +187,8 @@ func (m *defaultPost_likesModel) FindUIDPostLikeStatus(ctx context.Context, para return results, nil } + +func (c customPost_likesModel) Count(ctx context.Context, target string, likeType domain.LikeType) (int64, error) { + // TODO implement me + panic("implement me") +} diff --git a/internal/model/mongo/post_model.go b/internal/model/mongo/post_model.go index 998bde5..9024de8 100644 --- a/internal/model/mongo/post_model.go +++ b/internal/model/mongo/post_model.go @@ -1,6 +1,7 @@ package model import ( + "app-cloudep-tweeting-service/internal/domain" "context" "errors" "fmt" @@ -24,6 +25,7 @@ type ( DeleteMany(ctx context.Context, id ...string) (int64, error) UpdateOptional(ctx context.Context, data *Post) (*mongo.UpdateResult, error) Find(ctx context.Context, param *QueryPostModelReq) ([]*Post, int64, error) + IncDecLikeDislikeCountLogic(ctx context.Context, param *PostReactionAction) error } customPostModel struct { @@ -192,3 +194,39 @@ func (m *defaultPostModel) Find(ctx context.Context, param *QueryPostModelReq) ( return nil, 0, err } } + +func (c *customPostModel) IncDecLikeDislikeCountLogic(ctx context.Context, param *PostReactionAction) error { + // 建立篩選條件,找到要更新的貼文 + filter := bson.M{"_id": param.PostID} + + // 初始化更新操作 + update := bson.M{} + + // 根據 ReactionType 和 IsIncrement 決定更新邏輯 + if param.ReactionType == domain.LikeTypeLike { + if param.IsIncrement { + // 增加 like 計數 + update = bson.M{"$inc": bson.M{"like": 1}} + } else { + // 減少 like 計數 + update = bson.M{"$inc": bson.M{"like": -1}} + } + } else if param.ReactionType == domain.LikeTypeDisLike { + if param.IsIncrement { + // 增加 dislike 計數 + update = bson.M{"$inc": bson.M{"dislike": 1}} + } else { + // 減少 dislike 計數 + update = bson.M{"$inc": bson.M{"dislike": -1}} + } + } + + // 執行更新操作 + key := prefixPostCacheKey + param.PostID + _, err := c.conn.UpdateOne(ctx, key, filter, update) + if err != nil { + return err // 返回錯誤信息 + } + + return nil // 成功返回 nil +} diff --git a/internal/server/postservice/post_service_server.go b/internal/server/postservice/post_service_server.go index 16e5576..43968db 100644 --- a/internal/server/postservice/post_service_server.go +++ b/internal/server/postservice/post_service_server.go @@ -46,8 +46,14 @@ func (s *PostServiceServer) ListPosts(ctx context.Context, in *tweeting.QueryPos return l.ListPosts(in) } +// IncDecLikeDislikeCount 增減數量 +func (s *PostServiceServer) IncDecLikeDislikeCount(ctx context.Context, in *tweeting.IncDecLikeDislikeCountReq) (*tweeting.OKResp, error) { + l := postservicelogic.NewIncDecLikeDislikeCountLogic(ctx, s.svcCtx) + return l.IncDecLikeDislikeCount(in) +} + // Like 點讚/取消讚 貼文 -func (s *PostServiceServer) Like(ctx context.Context, in *tweeting.LikeReq) (*tweeting.OKResp, error) { +func (s *PostServiceServer) Like(ctx context.Context, in *tweeting.LikeReq) (*tweeting.PostReactionActionResp, error) { l := postservicelogic.NewLikeLogic(ctx, s.svcCtx) return l.Like(in) }