From 518e1673fece8ffc17db52b0e356c00704baabda Mon Sep 17 00:00:00 2001 From: "daniel.w" Date: Thu, 29 Aug 2024 17:33:57 +0800 Subject: [PATCH] add list posts --- generate/protobuf/tweeting.proto | 9 +- internal/domain/const.go | 13 +++ .../logic/postservice/list_posts_logic.go | 86 ++++++++++++++++++- internal/model/mongo/post_model.go | 73 ++++++++++++++++ 4 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 internal/domain/const.go diff --git a/generate/protobuf/tweeting.proto b/generate/protobuf/tweeting.proto index 6f6bea9..bbc7229 100644 --- a/generate/protobuf/tweeting.proto +++ b/generate/protobuf/tweeting.proto @@ -51,10 +51,9 @@ message UpdatePostReq { // 查詢貼文的請求 message QueryPostsReq { - repeated int64 user_id = 1; // 可選:根據用戶ID篩選貼文 - repeated int64 id = 2; // 可選:根據貼文ID篩選貼文 - repeated string tags = 3; // 可選:根據標籤篩選貼文 - optional bool only_ads = 4; // 可選:是否只顯示廣告 + repeated string uid = 1; // 可選:根據用戶ID篩選貼文 + repeated string id = 2; // 可選:根據貼文ID篩選貼文 + optional int32 only_ads = 4; // 可選:是否只顯示廣告 0 不篩選 1 只顯示廣告 2 不顯示廣告 int32 page_index = 5; // 分頁的頁碼 int32 page_size = 6; // 每頁顯示的數量 } @@ -62,7 +61,7 @@ message QueryPostsReq { // 貼文詳情 message PostDetailItem { string post_id = 1; // 貼文ID - int64 user_id = 2; // 發佈用戶ID + string uid = 2; // 發佈用戶ID string content = 3; // 貼文內容 repeated string tags = 4; // 標籤 repeated Media media = 5; // 圖片URL diff --git a/internal/domain/const.go b/internal/domain/const.go new file mode 100644 index 0000000..0e7211b --- /dev/null +++ b/internal/domain/const.go @@ -0,0 +1,13 @@ +package domain + +type AdType int32 + +func (a AdType) ToInt32() int32 { + return int32(a) +} + +const ( + AdTypeAll AdType = iota + AdTypeOnlyAd + AdTypeOnlyNotAd +) diff --git a/internal/logic/postservice/list_posts_logic.go b/internal/logic/postservice/list_posts_logic.go index abba88d..b8bf565 100644 --- a/internal/logic/postservice/list_posts_logic.go +++ b/internal/logic/postservice/list_posts_logic.go @@ -1,10 +1,13 @@ package postservicelogic import ( - "context" - "app-cloudep-tweeting-service/gen_result/pb/tweeting" + "app-cloudep-tweeting-service/internal/domain" + model "app-cloudep-tweeting-service/internal/model/mongo" "app-cloudep-tweeting-service/internal/svc" + ers "code.30cm.net/digimon/library-go/errs" + "context" + "google.golang.org/protobuf/proto" "github.com/zeromicro/go-zero/core/logx" ) @@ -23,9 +26,84 @@ func NewListPostsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListPos } } +type listReq struct { + OnlyAdds int32 `json:"only_adds" validate:"oneof=0 1 2 3"` + PageSize int64 `json:"page_size" validate:"required"` + PageIndex int64 `json:"page_index" validate:"required"` +} + // ListPosts 查詢貼文 func (l *ListPostsLogic) ListPosts(in *tweeting.QueryPostsReq) (*tweeting.ListPostsResp, error) { - // todo: add your logic here and delete this line + // 驗證資料 + if err := l.svcCtx.Validate.ValidateAll(&listReq{ + PageSize: int64(in.GetPageSize()), + PageIndex: int64(in.GetPageIndex()), + OnlyAdds: in.GetOnlyAds(), + }); err != nil { + return nil, ers.InvalidFormat(err.Error()) + } - return &tweeting.ListPostsResp{}, nil + query := &model.QueryPostModelReq{ + UID: in.GetUid(), + Id: in.GetId(), + PageSize: int64(in.GetPageSize()), + PageIndex: int64(in.GetPageIndex()), + } + + if in.OnlyAds != nil { + switch in.GetOnlyAds() { + case domain.AdTypeOnlyAd.ToInt32(): + query.OnlyAds = proto.Bool(true) + case domain.AdTypeOnlyNotAd.ToInt32(): + query.OnlyAds = proto.Bool(false) + default: + } + } + + find, count, err := l.svcCtx.PostModel.Find(l.ctx, query) + if err != nil { + e := domain.PostMongoErrorL( + logx.WithContext(l.ctx), + []logx.LogField{ + {Key: "query", Value: query}, + {Key: "func", Value: "PostModel.Find"}, + {Key: "err", Value: err}, + }, + "failed to add new post").Wrap(err) + return nil, e + } + + result := make([]*tweeting.PostDetailItem, 0, count) + + for _, item := range find { + media := make([]*tweeting.Media, 0, len(item.Media)) + for _, subItem := range item.Media { + media = append(media, &tweeting.Media{ + Type: subItem.Type, + Url: subItem.Links, + }) + } + + result = append(result, &tweeting.PostDetailItem{ + PostId: item.ID.Hex(), + Uid: item.UID, + Content: item.Content, + Tags: item.Tags, + Media: media, + IsAd: item.IsAd, + CreatedAt: item.CreateAt, + UpdateAt: item.UpdateAt, + LikeCount: int64(item.Like), + DislikeCount: int64(item.DisLike), + }) + } + + return &tweeting.ListPostsResp{ + Posts: result, + Page: &tweeting.Pager{ + Total: count, + Index: int64(in.GetPageIndex()), + Size: int64(in.GetPageSize()), + }, + }, nil } diff --git a/internal/model/mongo/post_model.go b/internal/model/mongo/post_model.go index d57daab..f968892 100644 --- a/internal/model/mongo/post_model.go +++ b/internal/model/mongo/post_model.go @@ -2,6 +2,7 @@ package model import ( "context" + "errors" "fmt" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/stores/cache" @@ -9,6 +10,7 @@ import ( "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" "time" ) @@ -21,11 +23,20 @@ type ( postModel 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) } customPostModel struct { *defaultPostModel } + + QueryPostModelReq struct { + UID []string + Id []string + OnlyAds *bool + PageSize int64 + PageIndex int64 + } ) // NewPostModel returns a model for the mongo. @@ -118,3 +129,65 @@ func (m *defaultPostModel) UpdateOptional(ctx context.Context, data *Post) (*mon return res, err } + +// Find 貼文列表 +func (m *defaultPostModel) Find(ctx context.Context, param *QueryPostModelReq) ([]*Post, int64, error) { + filter := bson.M{} + + // 添加 UID 過濾條件 + if len(param.UID) > 0 { + filter["uid"] = bson.M{"$in": param.UID} + } + + // 添加 ID 過濾條件 + if len(param.Id) > 0 { + var ids []primitive.ObjectID + for _, item := range param.Id { + oid, err := primitive.ObjectIDFromHex(item) + if err != nil { + // log + continue + } + ids = append(ids, oid) + } + + filter["_id"] = bson.M{"$in": ids} + } + + // 添加 OnlyAds 過濾條件 + if param.OnlyAds != nil { + // true 是廣告 false 不是廣告 , 沒寫就是不過率 + filter["is_ad"] = *param.OnlyAds + } + + // 分頁處理 + options := options.Find() + if param.PageSize > 0 { + options.SetLimit(param.PageSize) + } + if param.PageIndex > 0 { + options.SetSkip((param.PageIndex - 1) * param.PageSize) + } + + // 計算總數(不考慮分頁) + totalCount, err := m.conn.CountDocuments(ctx, filter) + if err != nil { + return nil, 0, err + } + + result := make([]*Post, 0, param.PageSize) + // 執行查詢 + err = m.conn.Find(ctx, &result, filter, options) + if err != nil { + return nil, 0, err + } + + switch { + case err == nil: + return result, totalCount, nil + case errors.Is(err, monc.ErrNotFound): + return nil, 0, ErrNotFound + default: + return nil, 0, err + } +}