234 lines
5.5 KiB
Go
234 lines
5.5 KiB
Go
package model
|
|
|
|
import (
|
|
"app-cloudep-tweeting-service/internal/domain"
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/zeromicro/go-zero/core/logx"
|
|
"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 _ PostModel = (*customPostModel)(nil)
|
|
|
|
type (
|
|
// PostModel is an interface to be customized, add more methods here,
|
|
// and implement the added methods in customPostModel.
|
|
PostModel interface {
|
|
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)
|
|
IncDecLikeDislikeCountLogic(ctx context.Context, param *PostReactionAction) error
|
|
}
|
|
|
|
customPostModel struct {
|
|
*defaultPostModel
|
|
}
|
|
|
|
QueryPostModelReq struct {
|
|
UID []string
|
|
Id []string
|
|
OnlyAds *bool
|
|
PageSize int64
|
|
PageIndex int64
|
|
}
|
|
)
|
|
|
|
// NewPostModel returns a model for the mongo.
|
|
func NewPostModel(url, db, collection string, c cache.CacheConf) PostModel {
|
|
conn := monc.MustNewModel(url, db, collection, c)
|
|
return &customPostModel{
|
|
defaultPostModel: newDefaultPostModel(conn),
|
|
}
|
|
}
|
|
|
|
func (m *defaultPostModel) DeleteMany(ctx context.Context, id ...string) (int64, error) {
|
|
objectIDs := make([]primitive.ObjectID, 0, len(id))
|
|
key := make([]string, 0, len(id))
|
|
|
|
// prepare
|
|
for _, item := range id {
|
|
oid, err := primitive.ObjectIDFromHex(item)
|
|
if err != nil {
|
|
logx.WithCallerSkip(1).WithFields(
|
|
logx.Field("func", "defaultPostModel.DeleteMany"),
|
|
logx.Field("id", item),
|
|
).Error(err.Error())
|
|
|
|
continue
|
|
}
|
|
objectIDs = append(objectIDs, oid)
|
|
key = append(key, prefixPostCacheKey+item)
|
|
}
|
|
|
|
// 檢查是否有有效的 ObjectIDs
|
|
if len(objectIDs) == 0 {
|
|
return 0, ErrNotFound
|
|
}
|
|
|
|
// 刪除文檔
|
|
res, err := m.conn.DeleteMany(ctx, bson.M{"_id": bson.M{"$in": objectIDs}})
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
err = m.conn.DelCache(ctx, key...)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return res, err
|
|
}
|
|
|
|
func (m *defaultPostModel) UpdateOptional(ctx context.Context, data *Post) (*mongo.UpdateResult, error) {
|
|
update := bson.M{"$set": bson.M{}}
|
|
|
|
if data.UID != "" {
|
|
update["$set"].(bson.M)["uid"] = data.UID
|
|
}
|
|
|
|
if data.Content != "" {
|
|
update["$set"].(bson.M)["content"] = data.Content
|
|
}
|
|
|
|
if data.Status != 0 {
|
|
update["$set"].(bson.M)["status"] = data.Status
|
|
}
|
|
|
|
if data.IsAd {
|
|
update["$set"].(bson.M)["is_ad"] = data.IsAd
|
|
}
|
|
|
|
if len(data.Tags) > 0 {
|
|
update["$set"].(bson.M)["tags"] = data.Tags
|
|
}
|
|
|
|
if len(data.Media) > 0 {
|
|
update["$set"].(bson.M)["media_url"] = data.Media
|
|
}
|
|
|
|
if data.Like != 0 {
|
|
update["$set"].(bson.M)["like"] = data.Like
|
|
}
|
|
|
|
if data.DisLike != 0 {
|
|
update["$set"].(bson.M)["dislike"] = data.DisLike
|
|
}
|
|
|
|
// UpdateAt 是每次都需要更新的,不用檢查
|
|
update["$set"].(bson.M)["updateAt"] = time.Now().UTC().UnixNano()
|
|
fmt.Println("update map", update)
|
|
|
|
key := prefixPostCacheKey + data.ID.Hex()
|
|
res, err := m.conn.UpdateOne(ctx, key, bson.M{"_id": data.ID}, update)
|
|
|
|
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
|
|
}
|
|
|
|
// 分頁處理
|
|
opts := options.Find()
|
|
opts.SetSort(bson.D{{"create_time", -1}})
|
|
if param.PageSize > 0 {
|
|
opts.SetLimit(param.PageSize)
|
|
}
|
|
if param.PageIndex > 0 {
|
|
opts.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, opts)
|
|
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
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|