package feed import ( "context" "feedsystem_video_go/internal/social" "feedsystem_video_go/internal/video" "time" "gorm.io/gorm" ) type FeedRepository struct { db *gorm.DB } func NewFeedRepository(db *gorm.DB) *FeedRepository { return &FeedRepository{db: db} } // 查询最新视频. limit: 查询数量 latestBefore: 查询早于此时间的视频(零值则不限制) func (repo *FeedRepository) ListLatest(ctx context.Context, limit int, latestBefore time.Time) ([]*video.Video, error) { var videos []*video.Video query := repo.db.WithContext(ctx).Model(&video.Video{}). Order("create_time DESC") if !latestBefore.IsZero() { query = query.Where("create_time < ?", latestBefore) } if err := query.Limit(limit).Find(&videos).Error; err != nil { return nil, err } return videos, nil } // 查询点赞数最多的视频. limit: 查询数量 cursor: 游标 func (repo *FeedRepository) ListLikesCountWithCursor(ctx context.Context, limit int, cursor *LikesCountCursor) ([]*video.Video, error) { var videos []*video.Video query := repo.db.WithContext(ctx).Model(&video.Video{}). Order("likes_count DESC, id DESC") if cursor != nil { query = query.Where( "(likes_count < ?) OR (likes_count = ? AND id < ?)", cursor.LikesCount, cursor.LikesCount, cursor.ID, ) } if err := query.Limit(limit).Find(&videos).Error; err != nil { return nil, err } return videos, nil } // 查询关注用户的视频. limit: 查询数量 viewerAccountID: 查看者账户ID latestBefore: 查询早于此时间的视频(零值则不限制) func (repo *FeedRepository) ListByFollowing(ctx context.Context, limit int, viewerAccountID uint, latestBefore time.Time) ([]*video.Video, error) { var videos []*video.Video query := repo.db.WithContext(ctx).Model(&video.Video{}). Order("create_time DESC") if viewerAccountID > 0 { followingSubQuery := repo.db.WithContext(ctx). Model(&social.Social{}). Select("vlogger_id"). Where("follower_id = ?", viewerAccountID) query = query.Where("author_id IN (?)", followingSubQuery) } if !latestBefore.IsZero() { query = query.Where("create_time < ?", latestBefore) } if err := query.Limit(limit).Find(&videos).Error; err != nil { return nil, err } return videos, nil } // 查询热门视频. limit: 查询数量 popularityBefore: 查询热度低于此值的视频 timeBefore: 查询早于此时间的视频 idBefore: 查询ID小于此值的视频 func (repo *FeedRepository) ListByPopularity(ctx context.Context, limit int, popularityBefore int64, timeBefore time.Time, idBefore uint) ([]*video.Video, error) { var videos []*video.Video query := repo.db.WithContext(ctx).Model(&video.Video{}). Order("popularity DESC, create_time DESC, id DESC") // 只有当游标完整提供时才加过滤(popularity 允许为 0) if !timeBefore.IsZero() && idBefore > 0 { query = query.Where( "(popularity < ?) OR (popularity = ? AND create_time < ?) OR (popularity = ? AND create_time = ? AND id < ?)", popularityBefore, popularityBefore, timeBefore, popularityBefore, timeBefore, idBefore, ) } if err := query.Limit(limit).Find(&videos).Error; err != nil { return nil, err } return videos, nil } func (repo *FeedRepository) GetByIDs(ctx context.Context, ids []uint) ([]*video.Video, error) { var videos []*video.Video if len(ids) == 0 { return videos, nil } if err := repo.db.WithContext(ctx).Model(&video.Video{}). Where("id IN ?", ids).Find(&videos).Error; err != nil { return nil, err } return videos, nil } func (repo *FeedRepository) ListByTag(ctx context.Context, tagName string, limit int) ([]*video.Video, error) { var videos []*video.Video err := repo.db.WithContext(ctx).Model(&video.Video{}).Table("videos"). Joins("JOIN video_tags ON video_tags.video_id = videos.id"). Joins("JOIN tags ON tags.id = video_tags.tag_id"). Where("tags.name = ?", tagName). Order("videos.create_time desc"). Limit(limit). Find(&videos).Error return videos, err }