609 lines
19 KiB
Go
Executable File
609 lines
19 KiB
Go
Executable File
package mediamod
|
||
|
||
import (
|
||
"91porn-server/models"
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"time"
|
||
|
||
"91porn-server/common/db"
|
||
"91porn-server/common/log"
|
||
|
||
"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"
|
||
)
|
||
|
||
const table = models.Media
|
||
|
||
func coll(t *db.MongoTool) *db.MongoTool {
|
||
if t == nil {
|
||
return mdb.Coll(table)
|
||
}
|
||
return t.Coll(table)
|
||
}
|
||
|
||
func initIndex() {
|
||
many := []mongo.IndexModel{
|
||
{
|
||
Keys: bson.D{{Key: "lsjId", Value: 1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "sId", Value: 1}, {Key: "sortCode", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "sId", Value: 1}, {Key: "sectionSort", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "tags", Value: 1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "tags", Value: 1}, {"isDelete", 1}, {"status", 1}, {"hot", -1}, {"createdAt", -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "tags", Value: 1}, {"isDelete", 1}, {"status", 1}, {"countCollect", -1}, {"createdAt", -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "tags", Value: 1}, {"isDelete", 1}, {"status", 1}, {"countBrowse", -1}, {"createdAt", -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "tags", Value: 1}, {"isDelete", 1}, {"status", 1}, {"createdAt", -1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "kind", Value: 1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "isActive", Value: 1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "specialSubjectID", Value: 1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "updatedAt", Value: -1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "createdAt", Value: -1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "mediaContentId", Value: 1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "title", Value: 1}},
|
||
}, { // 年度排行需要
|
||
Keys: bson.D{{Key: "mediaType", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {"countBrowse", -1}, {Key: "createdAt", Value: -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "sId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "createdAt", Value: -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "sId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "countLike", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "sId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "countCollect", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "sId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "countBrowse", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "sId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "hot", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
},
|
||
// 首页优化
|
||
{
|
||
Keys: bson.D{{Key: "mId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "createdAt", Value: -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "mId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "countLike", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "mId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "countBrowse", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "mId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "countCollect", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
}, {
|
||
Keys: bson.D{{Key: "mId", Value: 1}, {Key: "status", Value: 1}, {"isDelete", 1}, {Key: "hot", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
},
|
||
{
|
||
Keys: bson.D{{Key: "mId", Value: 1}, {Key: "sortCode", Value: -1}, {Key: "createdAt", Value: -1}},
|
||
},
|
||
{
|
||
Keys: bson.D{
|
||
{Key: "mId", Value: 1},
|
||
{Key: "status", Value: 1},
|
||
{Key: "isDelete", Value: 1},
|
||
{Key: "latestPublishedAt", Value: -1},
|
||
{Key: "contentUpdateTime", Value: -1},
|
||
{Key: "createdAt", Value: -1},
|
||
{Key: "_id", Value: -1},
|
||
},
|
||
},
|
||
}
|
||
if _, err := coll(nil).CreateIndex(many); err != nil {
|
||
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
|
||
}
|
||
}
|
||
|
||
// Init 初始化索引
|
||
func Init() {
|
||
mdb = db.Init(table)
|
||
initIndex()
|
||
}
|
||
|
||
// GetList 获取列表
|
||
func GetList(cond bson.M, skip, limit int64, sort bson.D) (res []*Media, hasNext bool, err error) {
|
||
opts := options.Find()
|
||
if len(sort) > 0 {
|
||
opts.SetSort(sort)
|
||
}
|
||
opts = opts.SetSort(sort).SetSkip(skip).SetLimit(limit + 1)
|
||
if err = coll(nil).Find(&res, cond, opts); err != nil {
|
||
return
|
||
}
|
||
// 判断下一页
|
||
if len(res) > int(limit) {
|
||
hasNext = true
|
||
res = res[:limit]
|
||
}
|
||
|
||
return
|
||
}
|
||
|
||
// QueryAllList 分页查询文档
|
||
func QueryAllList(filter primitive.M, opts ...*options.FindOptions) (out []*Media, err error) {
|
||
if err = coll(nil).Find(&out, filter, opts...); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "QueryAllList", table, "Find", err),
|
||
log.Any("filter", filter),
|
||
log.Any("opts", opts),
|
||
)
|
||
return nil, err
|
||
}
|
||
return
|
||
}
|
||
|
||
// QueryAllCount 查询文档条目数
|
||
func QueryAllCount(filter primitive.M) (int64, error) {
|
||
if count, err := coll(nil).Count(filter); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "QueryAllCount", table, "Count", err),
|
||
log.Any("filter", filter),
|
||
)
|
||
return 0, err
|
||
} else {
|
||
return count, nil
|
||
}
|
||
}
|
||
|
||
// GetLatestIDForESSync 固定本轮同步的 ID 上界,仅读取已有主键索引。
|
||
func GetLatestIDForESSync() (primitive.ObjectID, error) {
|
||
var data []*Media
|
||
opts := options.Find().SetSort(bson.D{{Key: "_id", Value: -1}}).
|
||
SetProjection(bson.M{"_id": 1}).SetHint("_id_").SetLimit(1).SetMaxTime(30 * time.Second)
|
||
if err := coll(nil).Find(&data, bson.M{}, opts); err != nil {
|
||
return primitive.NilObjectID, err
|
||
}
|
||
if len(data) == 0 {
|
||
return primitive.NilObjectID, nil
|
||
}
|
||
return data[0].ID, nil
|
||
}
|
||
|
||
// GetListForESSync 不限制更新时间上界,防止浏览等持续更新使记录逃出同步窗口。
|
||
// 使用稳定的 ID 游标,避免修改 updateTime 导致 skip 分页漏数据。
|
||
func GetListForESSync(since time.Time, after, maxID primitive.ObjectID, size int) (data []*Media, err error) {
|
||
query := bson.M{
|
||
"updateTime": bson.M{"$gte": since},
|
||
"_id": bson.M{"$gt": after, "$lte": maxID},
|
||
}
|
||
opts := options.Find().SetSort(bson.D{{Key: "_id", Value: 1}}).
|
||
SetHint("_id_").SetLimit(int64(size)).SetMaxTime(30 * time.Second)
|
||
err = coll(nil).Find(&data, query, opts)
|
||
return
|
||
}
|
||
|
||
var MediaNotFound = errors.New("media not found")
|
||
|
||
// GetInfoByMediaCenterId 通过mediaCenterId获取详细信息
|
||
func GetInfoByMediaCenterId(mediaCenterId uint) (Media, error) {
|
||
v := Media{}
|
||
if err := coll(nil).FindOne(&v, bson.M{"mediaCenterId": mediaCenterId, "isDelete": false}); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInfoByMediaCenterId", table, "FindOne", err),
|
||
log.Any("mediaCenterId", mediaCenterId),
|
||
)
|
||
return v, err
|
||
}
|
||
|
||
if v.ID.IsZero() {
|
||
return v, MediaNotFound
|
||
}
|
||
|
||
return v, nil
|
||
}
|
||
|
||
// GetInfoByTitle 通过标题获取详细信息
|
||
func GetInfoByTitle(title string) (Media, error) {
|
||
v := Media{}
|
||
if err := coll(nil).FindOne(&v, bson.M{"title": title, "isDelete": false}); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInfoByTitle", table, "FindOne", err),
|
||
log.Any("title", title),
|
||
)
|
||
return v, err
|
||
}
|
||
|
||
if v.ID.IsZero() {
|
||
return v, MediaNotFound
|
||
}
|
||
|
||
return v, nil
|
||
}
|
||
|
||
// GetInfo 通过id获取详细信息
|
||
func GetInfo(id primitive.ObjectID) (Media, error) {
|
||
v := Media{}
|
||
if err := coll(nil).FindOne(&v, bson.M{"_id": id}); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInfo", table, "FindOne", err),
|
||
log.Any("id", id),
|
||
)
|
||
return v, err
|
||
}
|
||
|
||
if v.ID.IsZero() {
|
||
return v, errors.New("record not found")
|
||
}
|
||
|
||
return v, nil
|
||
}
|
||
|
||
func GetListByIds(ids []primitive.ObjectID) (list []Media, res map[primitive.ObjectID]Media, err error) {
|
||
if err := coll(nil).Find(&list, bson.M{"_id": bson.M{"$in": ids}}); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetListByIds", table, "Find", err),
|
||
log.Any("ids", ids),
|
||
)
|
||
return nil, nil, err
|
||
}
|
||
res = make(map[primitive.ObjectID]Media)
|
||
for _, v := range list {
|
||
res[v.ID] = v
|
||
}
|
||
return list, res, nil
|
||
}
|
||
|
||
// IncreaseCountLikeByIDs 更新媒体点赞数
|
||
func IncreaseCountLikeByIDs(value int, ids ...primitive.ObjectID) (err error) {
|
||
var query = bson.M{}
|
||
if len(ids) == 1 {
|
||
query["_id"] = ids[0]
|
||
} else {
|
||
query["_id"] = bson.M{"$in": ids}
|
||
}
|
||
if _, err = coll(nil).UpdateOne(query, bson.M{"$inc": bson.M{"countLike": value}}); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncreaseLikeCountByID", table, "UpdateOne", err),
|
||
log.Any("id", ids),
|
||
log.Any("value", value),
|
||
)
|
||
return
|
||
}
|
||
return
|
||
}
|
||
|
||
// IncreaseCountShareByID 累计短剧真实分享次数,供推荐互动分计算。
|
||
func IncreaseCountShareByID(id primitive.ObjectID, value int) error {
|
||
_, err := coll(nil).UpdateOne(bson.M{"_id": id, "mediaType": MediaTypeDrama}, bson.M{"$inc": bson.M{"countShare": value}})
|
||
return err
|
||
}
|
||
|
||
// IncrCommentCountByID 更新媒体评论数
|
||
func IncrCommentCountByID(id primitive.ObjectID, value int) (err error) {
|
||
if _, err = coll(nil).UpdateOne(bson.M{"_id": id}, bson.M{"$inc": bson.M{"countComment": value}}); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncrCommentCountByID", table, "UpdateOne", err),
|
||
log.Any("id", id),
|
||
log.Any("value", value),
|
||
)
|
||
return
|
||
}
|
||
return
|
||
}
|
||
|
||
// QueryMediaByID 查询文档
|
||
func QueryMediaByID(filter primitive.M) (out *Media, err error) {
|
||
if err = coll(nil).FindOne(&out, filter); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "QueryAllList", table, "Find", err),
|
||
log.Any("filter", filter),
|
||
)
|
||
return nil, err
|
||
}
|
||
return
|
||
}
|
||
|
||
// QueryMediaByCond 查询文档
|
||
func QueryMediaByCond(filter primitive.M, opts *options.FindOptions) (out []*Media, err error) {
|
||
if err = coll(nil).Find(&out, filter, opts); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "QueryAllList", table, "Find", err),
|
||
log.Any("filter", filter),
|
||
)
|
||
return nil, err
|
||
}
|
||
return
|
||
}
|
||
|
||
// Insert 插入记录
|
||
func Insert(t *db.MongoTool, d Media) (data primitive.ObjectID, err error) {
|
||
normalizeLatestPublishedAt(&d)
|
||
result, err := coll(t).InsertOne(&d)
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Insert", table, "InsertOne", err))
|
||
return
|
||
}
|
||
byteID, err := json.Marshal(result.InsertedID)
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Insert", table, "Marshal", err))
|
||
return
|
||
}
|
||
if err = data.UnmarshalJSON(byteID); err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Insert", table, "UnmarshalJSON", err))
|
||
return
|
||
}
|
||
return
|
||
}
|
||
|
||
func InsertMany(c []Media) error {
|
||
for i := range c {
|
||
normalizeLatestPublishedAt(&c[i])
|
||
}
|
||
if _, err := coll(nil).InsertMany(c); err != nil {
|
||
log.Warn(fmt.Sprintf("METHOD-%s==> Model %s %s fail error:%+v:", "InsertMany", table, "InsertMany", err))
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func normalizeLatestPublishedAt(media *Media) {
|
||
if media == nil || media.Status != 1 || !media.LatestPublishedAt.IsZero() {
|
||
return
|
||
}
|
||
switch {
|
||
case !media.ContentUpdateTime.IsZero():
|
||
media.LatestPublishedAt = media.ContentUpdateTime
|
||
case !media.UpdateTime.IsZero():
|
||
media.LatestPublishedAt = media.UpdateTime
|
||
case !media.CreatedAt.IsZero():
|
||
media.LatestPublishedAt = media.CreatedAt
|
||
default:
|
||
media.LatestPublishedAt = time.Now()
|
||
}
|
||
}
|
||
|
||
// UpdateByID 根据id更新数据
|
||
func UpdateByID(t *db.MongoTool, id primitive.ObjectID, data map[string]interface{}) (int64, error) {
|
||
cond := bson.M{"_id": id}
|
||
return update(t, cond, data)
|
||
}
|
||
|
||
// UpdateByIDS 根据ids更新数据
|
||
func UpdateByIDS(t *db.MongoTool, ids []primitive.ObjectID, data map[string]interface{}) (int64, error) {
|
||
cond := bson.M{"_id": bson.M{"$in": ids}}
|
||
return update(t, cond, data)
|
||
}
|
||
|
||
// SectionVideosBySectionID 根据专题获取视频列表
|
||
func SectionVideosBySectionID(sectionID primitive.ObjectID, opts *options.FindOptions) ([]*Media, error) {
|
||
var out []*Media
|
||
return out, coll(nil).Find(&out, bson.M{"sId": sectionID, "isDelete": false, "status": 1}, opts)
|
||
}
|
||
|
||
type SectionWorkCount struct {
|
||
SectionID primitive.ObjectID `bson:"_id"`
|
||
Count int64 `bson:"count"`
|
||
}
|
||
|
||
// CountActiveDramaBySectionIDs groups all visible short dramas for one bounded topic page.
|
||
func CountActiveDramaBySectionIDs(sectionIDs []primitive.ObjectID) (map[primitive.ObjectID]int64, error) {
|
||
counts := make(map[primitive.ObjectID]int64, len(sectionIDs))
|
||
if len(sectionIDs) == 0 {
|
||
return counts, nil
|
||
}
|
||
var rows []SectionWorkCount
|
||
err := coll(nil).Aggregate(&rows, []bson.M{
|
||
{"$match": bson.M{"sId": bson.M{"$in": sectionIDs}, "mediaType": MediaTypeDrama, "status": 1, "isDelete": false}},
|
||
{"$group": bson.M{"_id": "$sId", "count": bson.M{"$sum": 1}}},
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
for _, row := range rows {
|
||
counts[row.SectionID] = row.Count
|
||
}
|
||
return counts, nil
|
||
}
|
||
|
||
// ListActiveDramaByInteractionScore computes the full-history ranking in MongoDB
|
||
// and only returns the requested page. The formula is:
|
||
// likes + collections*2 + comments*3 + shares*5.
|
||
func ListActiveDramaByInteractionScore(skip, limit int64) ([]*Media, error) {
|
||
if skip < 0 {
|
||
skip = 0
|
||
}
|
||
if limit <= 0 || limit > 101 {
|
||
limit = 21
|
||
}
|
||
var list []*Media
|
||
pipeline := []bson.M{
|
||
{"$match": bson.M{"mediaType": MediaTypeDrama, "status": 1, "isDelete": false}},
|
||
{"$addFields": bson.M{"_dramaInteractionScore": bson.M{"$add": []any{
|
||
bson.M{"$ifNull": []any{"$countLike", 0}},
|
||
bson.M{"$multiply": []any{bson.M{"$ifNull": []any{"$countCollect", 0}}, 2}},
|
||
bson.M{"$multiply": []any{bson.M{"$ifNull": []any{"$countComment", 0}}, 3}},
|
||
bson.M{"$multiply": []any{bson.M{"$ifNull": []any{"$countShare", 0}}, 5}},
|
||
}}}},
|
||
{"$sort": bson.D{{Key: "_dramaInteractionScore", Value: -1}, {Key: "latestPublishedAt", Value: -1}, {Key: "_id", Value: -1}}},
|
||
{"$skip": skip},
|
||
{"$limit": limit},
|
||
{"$project": bson.M{"_dramaInteractionScore": 0}},
|
||
}
|
||
err := coll(nil).Aggregate(&list, pipeline, options.Aggregate().SetAllowDiskUse(true))
|
||
return list, err
|
||
}
|
||
|
||
// update 更新数据
|
||
func update(t *db.MongoTool, cond primitive.M, data map[string]interface{}) (int64, error) {
|
||
result, err := coll(t).UpdateMany(cond, bson.M{"$set": bson.M(data)})
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Update", table, "UpdateMany", err),
|
||
log.Any("cond", cond),
|
||
log.Any("update", data),
|
||
)
|
||
return 0, err
|
||
}
|
||
|
||
return result.ModifiedCount, nil
|
||
}
|
||
|
||
// DeleteByID 删除数据
|
||
func DeleteByID(t *db.MongoTool, id primitive.ObjectID) error {
|
||
_, err := coll(t).UpdateOne(bson.M{"_id": id}, bson.M{"$set": bson.M{"isDelete": true}})
|
||
if err != nil {
|
||
if err == mongo.ErrNoDocuments {
|
||
return nil
|
||
} else {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DeleteByID", table, "DeleteMany", err), log.Any("id", id))
|
||
}
|
||
}
|
||
|
||
return err
|
||
}
|
||
|
||
// IncCollectCount 收藏次数增加
|
||
func IncCollectCount(id ObjectID, inc int) error {
|
||
query := bson.M{"_id": id}
|
||
update := bson.M{"$set": bson.M{"updateTime": time.Now()}, "$inc": bson.M{"countCollect": inc}}
|
||
_, err := coll(nil).UpdateOne(query, update)
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncCollectCount", table, "UpdateOne", err),
|
||
log.Any("id", id),
|
||
)
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// IncContentPurchasesCount 子集购买次数增加
|
||
func IncContentPurchasesCount(id ObjectID, inc int) error {
|
||
query := bson.M{"_id": id}
|
||
update := bson.M{"$set": bson.M{"updateTime": time.Now()}, "$inc": bson.M{"countContentPurchases": inc}}
|
||
_, err := coll(nil).UpdateOne(query, update)
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncPurchasesCount", table, "UpdateOne", err),
|
||
log.Any("id", id),
|
||
)
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// IncPurchasesCount 购买次数增加
|
||
func IncPurchasesCount(id ObjectID, inc int) error {
|
||
return IncPurchasesCountWithTool(nil, id, inc)
|
||
}
|
||
|
||
func IncPurchasesCountWithTool(t *db.MongoTool, id ObjectID, inc int) error {
|
||
query := bson.M{"_id": id}
|
||
update := bson.M{"$set": bson.M{"updateTime": time.Now()}, "$inc": bson.M{"countPurchases": inc}}
|
||
_, err := coll(t).UpdateOne(query, update)
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncPurchasesCount", table, "UpdateOne", err),
|
||
log.Any("id", id),
|
||
)
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// IncBrowseCount 浏览次数增加
|
||
func IncBrowseCount(id ObjectID, inc int) error {
|
||
query := bson.M{"_id": id}
|
||
update := bson.M{"$set": bson.M{"updateTime": time.Now()}, "$inc": bson.M{"countBrowse": inc}}
|
||
_, err := coll(nil).UpdateOne(query, update)
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncBrowseCount", table, "UpdateOne", err),
|
||
log.Any("id", id),
|
||
)
|
||
return err
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func Bulk(models []mongo.WriteModel) error {
|
||
_, err := coll(nil).Bulk(models, options.BulkWrite().SetOrdered(false))
|
||
return err
|
||
}
|
||
|
||
func GetListByLsjIds(lsjIds []string) ([]Media, error) {
|
||
filter := bson.M{
|
||
"lsjId": bson.M{"$in": lsjIds},
|
||
}
|
||
var ms []Media
|
||
return ms, coll(nil).Find(&ms, filter)
|
||
}
|
||
|
||
func GetListByLsjId(lsjId string) (Media, error) {
|
||
filter := bson.M{
|
||
"lsjId": lsjId,
|
||
}
|
||
var ms Media
|
||
return ms, coll(nil).FindOne(&ms, filter)
|
||
}
|
||
|
||
// UpdateMany 根据ids更新数据
|
||
func UpdateMany(t *db.MongoTool, filter bson.M, data bson.M) (int64, error) {
|
||
result, err := coll(t).UpdateMany(filter, data)
|
||
if err != nil {
|
||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Update", table, "UpdateMany", err),
|
||
log.Any("cond", filter),
|
||
log.Any("update", data),
|
||
)
|
||
return 0, err
|
||
}
|
||
|
||
return result.ModifiedCount, nil
|
||
}
|
||
|
||
// FindForReviewBatch 按 _id 游标分页扫描上架 Media,用于内容审查任务
|
||
// 仅扫描 status=1(上架)
|
||
func FindForReviewBatch(lastID primitive.ObjectID, limit int64) ([]*Media, error) {
|
||
cond := bson.M{"status": 1}
|
||
if !lastID.IsZero() {
|
||
cond["_id"] = bson.M{"$gt": lastID}
|
||
}
|
||
opts := options.Find().
|
||
SetSort(bson.D{{Key: "_id", Value: 1}}).
|
||
SetLimit(limit)
|
||
var list []*Media
|
||
if err := coll(nil).Find(&list, cond, opts); err != nil {
|
||
return nil, err
|
||
}
|
||
return list, nil
|
||
}
|
||
|
||
// CountForReview 上架 Media 总数;条件与 FindForReviewBatch 保持一致
|
||
func CountForReview() (int64, error) {
|
||
return coll(nil).Count(bson.M{"status": 1})
|
||
}
|
||
|
||
// UpdateForReview 内容审查通过后回写文本字段
|
||
// title 对应 Media.Title,content 对应 Media.Summary
|
||
func UpdateForReview(id primitive.ObjectID, title, content string) error {
|
||
set := bson.M{}
|
||
if title != "" {
|
||
set["title"] = title
|
||
}
|
||
if content != "" {
|
||
set["summary"] = content
|
||
}
|
||
if len(set) == 0 {
|
||
return nil
|
||
}
|
||
set["updateTime"] = time.Now()
|
||
_, err := coll(nil).UpdateOne(bson.M{"_id": id}, bson.M{"$set": set})
|
||
return err
|
||
}
|
||
|
||
// OffShelfManyForReview 内容审查命中后批量下架 Media(status -> 0)
|
||
// 仅当前 status=1 的会被改动
|
||
func OffShelfManyForReview(ids []primitive.ObjectID) error {
|
||
if len(ids) == 0 {
|
||
return nil
|
||
}
|
||
_, err := coll(nil).UpdateMany(
|
||
bson.M{"_id": bson.M{"$in": ids}, "status": 1},
|
||
bson.M{"$set": bson.M{"status": 0, "updateTime": time.Now()}},
|
||
)
|
||
return err
|
||
}
|