feature/post #1
|
@ -4,3 +4,25 @@ Etcd:
|
|||
Hosts:
|
||||
- 127.0.0.1:2379
|
||||
Key: tweeting.rpc
|
||||
|
||||
Cache:
|
||||
- Host: 127.0.0.1:7001
|
||||
type: cluster
|
||||
- Host: 127.0.0.1:7002
|
||||
type: cluster
|
||||
- Host: 127.0.0.1:7003
|
||||
type: cluster
|
||||
- Host: 127.0.0.1:7004
|
||||
type: cluster
|
||||
- Host: 127.0.0.1:7005
|
||||
type: cluster
|
||||
- Host: 127.0.0.1:7006
|
||||
type: cluster
|
||||
|
||||
Mongo:
|
||||
Schema: mongodb
|
||||
Host: 127.0.0.1
|
||||
User: ""
|
||||
Password: ""
|
||||
Port: "27017"
|
||||
Database: digimon_tweeting
|
|
@ -8,13 +8,12 @@ import (
|
|||
type Config struct {
|
||||
zrpc.RpcServerConf
|
||||
Mongo struct {
|
||||
Schema string
|
||||
User string
|
||||
Password string
|
||||
Host string
|
||||
Port string
|
||||
Database string
|
||||
Collection string
|
||||
Schema string
|
||||
User string
|
||||
Password string
|
||||
Host string
|
||||
Port string
|
||||
Database string
|
||||
}
|
||||
|
||||
// 快取
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package postservicelogic
|
||||
|
||||
import (
|
||||
"app-cloudep-tweeting-service/internal/domain"
|
||||
"context"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
|
@ -25,7 +26,18 @@ func NewDeletePostLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Delete
|
|||
|
||||
// DeletePost 刪除貼文
|
||||
func (l *DeletePostLogic) DeletePost(in *tweeting.DeletePostsReq) (*tweeting.OKResp, error) {
|
||||
// todo: add your logic here and delete this line
|
||||
_, err := l.svcCtx.PostModel.DeleteMany(l.ctx, in.GetPostId()...)
|
||||
if err != nil {
|
||||
e := domain.PostMongoErrorL(
|
||||
logx.WithContext(l.ctx),
|
||||
[]logx.LogField{
|
||||
{Key: "req", Value: in},
|
||||
{Key: "func", Value: "PostModel.DeletePost"},
|
||||
{Key: "err", Value: err},
|
||||
},
|
||||
"failed to add del post").Wrap(err)
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return &tweeting.OKResp{}, nil
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ func NewNewPostLogic(ctx context.Context, svcCtx *svc.ServiceContext) *NewPostLo
|
|||
|
||||
type newTweetingReq struct {
|
||||
UID string `json:"uid" validate:"required"`
|
||||
Content string `json:"content" validate:"required,gte=500"` // 貼文限制 500 字內
|
||||
Content string `json:"content" validate:"required,lte=500"` // 貼文限制 500 字內
|
||||
Tags []string `json:"tags"`
|
||||
MediaUrl []string `json:"media_url"`
|
||||
IsAd bool `json:"is_ad"` // default false
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
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"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
|
||||
"app-cloudep-tweeting-service/gen_result/pb/tweeting"
|
||||
"app-cloudep-tweeting-service/internal/svc"
|
||||
|
@ -23,9 +27,53 @@ func NewUpdatePostLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Update
|
|||
}
|
||||
}
|
||||
|
||||
type checkPostId struct {
|
||||
PostID string `validate:"required"`
|
||||
Content string `json:"content,omitempty" validate:"lte=500"`
|
||||
}
|
||||
|
||||
// UpdatePost 更新貼文
|
||||
func (l *UpdatePostLogic) UpdatePost(in *tweeting.UpdatePostReq) (*tweeting.OKResp, error) {
|
||||
// todo: add your logic here and delete this line
|
||||
// 驗證資料
|
||||
if err := l.svcCtx.Validate.ValidateAll(&checkPostId{
|
||||
PostID: in.GetPostId(),
|
||||
Content: in.GetContent(),
|
||||
}); err != nil {
|
||||
return nil, ers.InvalidFormat(err.Error())
|
||||
}
|
||||
// 沒有就沒有,有就走全覆蓋
|
||||
update := model.Post{}
|
||||
oid, err := primitive.ObjectIDFromHex(in.GetPostId())
|
||||
if err != nil {
|
||||
return nil, ers.InvalidFormat("failed to get correct post id")
|
||||
}
|
||||
update.ID = oid
|
||||
update.Tags = in.GetTags()
|
||||
// 將 Media 存入
|
||||
var media []model.Media
|
||||
for _, item := range in.GetMedia() {
|
||||
media = append(media, model.Media{
|
||||
Links: item.Url,
|
||||
Type: item.Type,
|
||||
})
|
||||
}
|
||||
update.Media = media
|
||||
update.Content = in.GetContent()
|
||||
update.Like = uint64(in.GetLikeCount())
|
||||
update.DisLike = uint64(in.GetDislikeCount())
|
||||
|
||||
_, err = l.svcCtx.PostModel.UpdateOptional(l.ctx, &update)
|
||||
if err != nil {
|
||||
e := domain.PostMongoErrorL(
|
||||
logx.WithContext(l.ctx),
|
||||
[]logx.LogField{
|
||||
{Key: "req", Value: in},
|
||||
{Key: "func", Value: "PostModel.UpdateOptional"},
|
||||
{Key: "err", Value: err},
|
||||
},
|
||||
"failed to add new post").Wrap(err)
|
||||
return nil, e
|
||||
}
|
||||
|
||||
return &tweeting.OKResp{}, nil
|
||||
}
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"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"
|
||||
"time"
|
||||
)
|
||||
|
||||
var _ PostModel = (*customPostModel)(nil)
|
||||
|
@ -12,6 +19,8 @@ type (
|
|||
// 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)
|
||||
}
|
||||
|
||||
customPostModel struct {
|
||||
|
@ -26,3 +35,86 @@ func NewPostModel(url, db, collection string, c cache.CacheConf) PostModel {
|
|||
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
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ func newDefaultPostModel(conn *monc.Model) *defaultPostModel {
|
|||
func (m *defaultPostModel) Insert(ctx context.Context, data *Post) error {
|
||||
if data.ID.IsZero() {
|
||||
data.ID = primitive.NewObjectID()
|
||||
data.CreateAt = time.Now()
|
||||
data.UpdateAt = time.Now()
|
||||
data.CreateAt = time.Now().UTC().UnixNano()
|
||||
data.UpdateAt = time.Now().UTC().UnixNano()
|
||||
}
|
||||
|
||||
key := prefixPostCacheKey + data.ID.Hex()
|
||||
|
@ -60,7 +60,7 @@ func (m *defaultPostModel) FindOne(ctx context.Context, id string) (*Post, error
|
|||
}
|
||||
|
||||
func (m *defaultPostModel) Update(ctx context.Context, data *Post) (*mongo.UpdateResult, error) {
|
||||
data.UpdateAt = time.Now()
|
||||
data.UpdateAt = time.Now().UTC().UnixNano()
|
||||
key := prefixPostCacheKey + data.ID.Hex()
|
||||
res, err := m.conn.UpdateOne(ctx, key, bson.M{"_id": data.ID}, bson.M{"$set": data})
|
||||
return res, err
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
|
@ -19,8 +17,10 @@ type Post struct {
|
|||
IsAd bool `bson:"is_ad" json:"is_ad"` // 此則貼文是否為廣告貼文
|
||||
Tags []string `bson:"tags" json:"tags"` // 本則貼文的標籤,不提供搜尋,僅提供顯示(存名字,ID 建立之後就不提供修改與刪除)
|
||||
Media []Media `bson:"media_url" json:"media_url"` // 網址
|
||||
UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
|
||||
CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"`
|
||||
Like uint64 `bson:"like" json:"like"` // 讚
|
||||
DisLike uint64 `bson:"dislike" json:"dislike"` // 不讚
|
||||
UpdateAt int64 `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
|
||||
CreateAt int64 `bson:"createAt,omitempty" json:"createAt,omitempty"`
|
||||
}
|
||||
|
||||
type Media struct {
|
||||
|
|
Loading…
Reference in New Issue