Files
urldb/db/repo/search_stat_repository.go

178 lines
5.1 KiB
Go
Raw Normal View History

2025-07-10 21:14:17 +08:00
package repo
import (
2025-07-21 23:38:28 +08:00
"fmt"
2025-07-10 21:14:17 +08:00
2025-07-18 09:42:07 +08:00
"github.com/ctwj/urldb/db/entity"
2025-08-11 01:34:07 +08:00
"github.com/ctwj/urldb/utils"
2025-07-10 21:14:17 +08:00
"gorm.io/gorm"
)
// SearchStatRepository 搜索统计Repository接口
type SearchStatRepository interface {
BaseRepository[entity.SearchStat]
RecordSearch(keyword, ip, userAgent string) error
GetDailyStats(days int) ([]entity.DailySearchStat, error)
GetHotKeywords(days int, limit int) ([]entity.KeywordStat, error)
GetSearchTrend(days int) ([]entity.DailySearchStat, error)
GetKeywordTrend(keyword string, days int) ([]entity.DailySearchStat, error)
2025-07-21 23:38:28 +08:00
GetSummary() (map[string]int64, error)
2025-08-13 15:22:01 +08:00
FindWithPaginationOrdered(page, limit int) ([]entity.SearchStat, int64, error)
2025-07-10 21:14:17 +08:00
}
// SearchStatRepositoryImpl 搜索统计Repository实现
type SearchStatRepositoryImpl struct {
BaseRepositoryImpl[entity.SearchStat]
}
// NewSearchStatRepository 创建搜索统计Repository
func NewSearchStatRepository(db *gorm.DB) SearchStatRepository {
return &SearchStatRepositoryImpl{
BaseRepositoryImpl: BaseRepositoryImpl[entity.SearchStat]{db: db},
}
}
2025-07-21 23:38:28 +08:00
// RecordSearch 记录搜索(每次都插入新记录)
2025-07-10 21:14:17 +08:00
func (r *SearchStatRepositoryImpl) RecordSearch(keyword, ip, userAgent string) error {
2025-07-21 23:38:28 +08:00
stat := entity.SearchStat{
Keyword: keyword,
Count: 1,
2025-08-11 01:34:07 +08:00
Date: utils.GetCurrentTime(), // 可保留 date 字段,实际用 created_at 统计
2025-07-21 23:38:28 +08:00
IP: ip,
UserAgent: userAgent,
2025-07-10 21:14:17 +08:00
}
2025-07-21 23:38:28 +08:00
return r.db.Create(&stat).Error
2025-07-10 21:14:17 +08:00
}
// GetDailyStats 获取每日统计
func (r *SearchStatRepositoryImpl) GetDailyStats(days int) ([]entity.DailySearchStat, error) {
var stats []entity.DailySearchStat
2025-07-21 23:38:28 +08:00
query := fmt.Sprintf(`
2025-07-10 21:14:17 +08:00
SELECT
date,
SUM(count) as total_searches,
COUNT(DISTINCT keyword) as unique_keywords
FROM search_stats
2025-07-21 23:38:28 +08:00
WHERE date >= CURRENT_DATE - INTERVAL '%d days'
2025-07-10 21:14:17 +08:00
GROUP BY date
ORDER BY date DESC
2025-07-21 23:38:28 +08:00
`, days)
2025-07-10 21:14:17 +08:00
2025-07-21 23:38:28 +08:00
err := r.db.Raw(query).Scan(&stats).Error
2025-07-10 21:14:17 +08:00
return stats, err
}
// GetHotKeywords 获取热门关键词
func (r *SearchStatRepositoryImpl) GetHotKeywords(days int, limit int) ([]entity.KeywordStat, error) {
var keywords []entity.KeywordStat
2025-07-21 23:38:28 +08:00
query := fmt.Sprintf(`
2025-07-10 21:14:17 +08:00
SELECT
keyword,
SUM(count) as count,
RANK() OVER (ORDER BY SUM(count) DESC) as rank
FROM search_stats
2025-07-21 23:38:28 +08:00
WHERE date >= CURRENT_DATE - INTERVAL '%d days'
2025-07-10 21:14:17 +08:00
GROUP BY keyword
ORDER BY count DESC
LIMIT ?
2025-07-21 23:38:28 +08:00
`, days)
2025-07-10 21:14:17 +08:00
2025-07-21 23:38:28 +08:00
err := r.db.Raw(query, limit).Scan(&keywords).Error
2025-07-10 21:14:17 +08:00
return keywords, err
}
// GetSearchTrend 获取搜索趋势
func (r *SearchStatRepositoryImpl) GetSearchTrend(days int) ([]entity.DailySearchStat, error) {
var stats []entity.DailySearchStat
2025-07-21 23:38:28 +08:00
query := fmt.Sprintf(`
2025-07-10 21:14:17 +08:00
SELECT
date,
SUM(count) as total_searches,
COUNT(DISTINCT keyword) as unique_keywords
FROM search_stats
2025-07-21 23:38:28 +08:00
WHERE date >= CURRENT_DATE - INTERVAL '%d days'
2025-07-10 21:14:17 +08:00
GROUP BY date
ORDER BY date ASC
2025-07-21 23:38:28 +08:00
`, days)
2025-07-10 21:14:17 +08:00
2025-07-21 23:38:28 +08:00
err := r.db.Raw(query).Scan(&stats).Error
2025-07-10 21:14:17 +08:00
return stats, err
}
// GetKeywordTrend 获取关键词趋势
func (r *SearchStatRepositoryImpl) GetKeywordTrend(keyword string, days int) ([]entity.DailySearchStat, error) {
var stats []entity.DailySearchStat
2025-07-21 23:38:28 +08:00
query := fmt.Sprintf(`
2025-07-10 21:14:17 +08:00
SELECT
date,
SUM(count) as total_searches,
COUNT(DISTINCT keyword) as unique_keywords
FROM search_stats
2025-07-21 23:38:28 +08:00
WHERE keyword = ? AND date >= CURRENT_DATE - INTERVAL '%d days'
2025-07-10 21:14:17 +08:00
GROUP BY date
ORDER BY date ASC
2025-07-21 23:38:28 +08:00
`, days)
2025-07-10 21:14:17 +08:00
2025-07-21 23:38:28 +08:00
err := r.db.Raw(query, keyword).Scan(&stats).Error
2025-07-10 21:14:17 +08:00
return stats, err
}
2025-07-21 23:38:28 +08:00
// GetSummary 获取搜索统计汇总
func (r *SearchStatRepositoryImpl) GetSummary() (map[string]int64, error) {
var total, today, week, month, keywords int64
2025-08-11 01:34:07 +08:00
now := utils.GetCurrentTime()
todayStr := now.Format(utils.TimeFormatDate)
weekStart := now.AddDate(0, 0, -int(now.Weekday())+1).Format(utils.TimeFormatDate) // 周一
2025-07-21 23:38:28 +08:00
monthStart := now.Format("2006-01") + "-01"
// 总搜索次数
if err := r.db.Model(&entity.SearchStat{}).Count(&total).Error; err != nil {
return nil, err
}
// 今日搜索次数
if err := r.db.Model(&entity.SearchStat{}).Where("DATE(created_at) = ?", todayStr).Count(&today).Error; err != nil {
return nil, err
}
// 本周搜索次数
if err := r.db.Model(&entity.SearchStat{}).Where("created_at >= ?", weekStart).Count(&week).Error; err != nil {
return nil, err
}
// 本月搜索次数
if err := r.db.Model(&entity.SearchStat{}).Where("created_at >= ?", monthStart).Count(&month).Error; err != nil {
return nil, err
}
// 总关键词数
if err := r.db.Model(&entity.SearchStat{}).Distinct("keyword").Count(&keywords).Error; err != nil {
return nil, err
}
return map[string]int64{
"total": total,
"today": today,
"week": week,
"month": month,
"keywords": keywords,
}, nil
}
2025-08-13 15:22:01 +08:00
// FindWithPaginationOrdered 按时间倒序分页查找搜索记录
func (r *SearchStatRepositoryImpl) FindWithPaginationOrdered(page, limit int) ([]entity.SearchStat, int64, error) {
var stats []entity.SearchStat
var total int64
offset := (page - 1) * limit
// 获取总数
if err := r.db.Model(&entity.SearchStat{}).Count(&total).Error; err != nil {
return nil, 0, err
}
// 获取分页数据,按创建时间倒序排列(最新的在前面)
err := r.db.Order("created_at DESC").Offset(offset).Limit(limit).Find(&stats).Error
return stats, total, err
}