init push
This commit is contained in:
208
backend/repo/pg/stat.go
Normal file
208
backend/repo/pg/stat.go
Normal file
@@ -0,0 +1,208 @@
|
||||
package pg
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
v1 "github.com/chaitin/panda-wiki/api/stat/v1"
|
||||
"github.com/chaitin/panda-wiki/domain"
|
||||
"github.com/chaitin/panda-wiki/store/cache"
|
||||
"github.com/chaitin/panda-wiki/store/pg"
|
||||
"github.com/chaitin/panda-wiki/utils"
|
||||
)
|
||||
|
||||
type StatRepository struct {
|
||||
db *pg.DB
|
||||
cache *cache.Cache
|
||||
}
|
||||
|
||||
func NewStatRepository(db *pg.DB, cahe *cache.Cache) *StatRepository {
|
||||
return &StatRepository{
|
||||
db: db,
|
||||
cache: cahe,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *StatRepository) CreateStatPage(ctx context.Context, stat *domain.StatPage) error {
|
||||
return r.db.WithContext(ctx).Model(&domain.StatPage{}).Create(stat).Error
|
||||
}
|
||||
|
||||
func (r *StatRepository) GetHotPages(ctx context.Context, kbID string) ([]*domain.HotPage, error) {
|
||||
var hotPages []*domain.HotPage
|
||||
if err := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("kb_id = ?", kbID).
|
||||
Where("node_id != '' ").
|
||||
Where("scene = ?", domain.StatPageSceneNodeDetail).
|
||||
Group("node_id").
|
||||
Select("node_id, COUNT(*) as count").
|
||||
Order("count DESC").
|
||||
Limit(10).
|
||||
Find(&hotPages).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hotPages, nil
|
||||
}
|
||||
|
||||
func (r *StatRepository) GetHotPagesNoLimit(ctx context.Context, kbID string) ([]*domain.HotPage, error) {
|
||||
var hotPages []*domain.HotPage
|
||||
if err := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("kb_id = ?", kbID).
|
||||
Where("node_id != '' ").
|
||||
Where("scene = ?", domain.StatPageSceneNodeDetail).
|
||||
Group("node_id").
|
||||
Select("node_id, COUNT(*) as count").
|
||||
Find(&hotPages).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hotPages, nil
|
||||
}
|
||||
|
||||
func (r *StatRepository) GetHotScene(ctx context.Context, kbID string) (map[domain.StatPageScene]int64, error) {
|
||||
var scenes map[domain.StatPageScene]int64
|
||||
if err := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("kb_id = ?", kbID).
|
||||
Group("scene").
|
||||
Select("scene, COUNT(*) as count").
|
||||
Order("count DESC").
|
||||
Limit(10).
|
||||
Find(&scenes).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return scenes, nil
|
||||
}
|
||||
|
||||
func (r *StatRepository) GetHotRefererHosts(ctx context.Context, kbID string) ([]*domain.HotRefererHost, error) {
|
||||
var hotRefererHosts []*domain.HotRefererHost
|
||||
if err := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("kb_id = ? AND referer_host != ?", kbID, "").
|
||||
Group("referer_host").
|
||||
Select("referer_host, COUNT(*) as count").
|
||||
Order("count DESC").
|
||||
Limit(10).
|
||||
Find(&hotRefererHosts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hotRefererHosts, nil
|
||||
}
|
||||
|
||||
func (r *StatRepository) GetHotBrowsers(ctx context.Context, kbID string) (*domain.HotBrowser, error) {
|
||||
var hotBrowsers *domain.HotBrowser
|
||||
var osCount []domain.BrowserCount
|
||||
var browserCount []domain.BrowserCount
|
||||
|
||||
query := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("kb_id = ?", kbID).
|
||||
Where("browser_name != '' ").
|
||||
Group("browser_name").
|
||||
Select("browser_name as name, COUNT(*) as count")
|
||||
if err := query.Order("count DESC").Limit(10).Find(&browserCount).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query = r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("kb_id = ?", kbID).
|
||||
Where("browser_os != '' ").
|
||||
Group("browser_os").
|
||||
Select("browser_os as name, COUNT(*) as count")
|
||||
if err := query.Order("count DESC").Limit(10).Find(&osCount).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hotBrowsers = &domain.HotBrowser{
|
||||
OS: osCount,
|
||||
Browser: browserCount,
|
||||
}
|
||||
|
||||
return hotBrowsers, nil
|
||||
}
|
||||
|
||||
func (r *StatRepository) GetStatPageCount(ctx context.Context, kbID string) (*v1.StatCountResp, error) {
|
||||
var count v1.StatCountResp
|
||||
if err := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("kb_id = ?", kbID).
|
||||
Select("COUNT(DISTINCT ip) as ip_count, COUNT(DISTINCT session_id) as session_count, COUNT(*) as page_visit_count").
|
||||
Scan(&count).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &count, nil
|
||||
}
|
||||
|
||||
func (r *StatRepository) GetInstantCount(ctx context.Context, kbID string) ([]*domain.InstantCountResp, error) {
|
||||
var instantCount []*domain.InstantCountResp
|
||||
if err := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("kb_id = ? AND created_at >= NOW() - INTERVAL '1h'", kbID).
|
||||
Select("date_trunc('minute', created_at) as time, COUNT(*) as count").
|
||||
Group("time").
|
||||
Order("time ASC").
|
||||
Find(&instantCount).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return instantCount, nil
|
||||
}
|
||||
|
||||
func (r *StatRepository) GetInstantPages(ctx context.Context, kbID string) ([]*domain.InstantPageResp, error) {
|
||||
var instantPages []*domain.InstantPageResp
|
||||
if err := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("kb_id = ?", kbID).
|
||||
Select("node_id, ip, scene, created_at,user_id").
|
||||
Order("created_at DESC").
|
||||
Limit(10).
|
||||
Find(&instantPages).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return instantPages, nil
|
||||
}
|
||||
|
||||
func (r *StatRepository) RemoveOldData(ctx context.Context) error {
|
||||
if err := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("created_at < ?", utils.GetTimeHourOffset(-24)).
|
||||
Delete(&domain.StatPage{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetYesterdayPVByNode 获取昨天的PV数据,按node_id分组
|
||||
func (r *StatRepository) GetYesterdayPVByNode(ctx context.Context) (map[string]int64, error) {
|
||||
type PVResult struct {
|
||||
NodeID string
|
||||
Count int64
|
||||
}
|
||||
|
||||
var results []PVResult
|
||||
if err := r.db.WithContext(ctx).Model(&domain.StatPage{}).
|
||||
Where("created_at < ?", utils.GetTimeHourOffset(0)).
|
||||
Where("created_at >= ?", utils.GetTimeHourOffset(-24)).
|
||||
Where("node_id != ?", "").
|
||||
Group("node_id").
|
||||
Select("node_id, COUNT(*) as count").
|
||||
Find(&results).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pvMap := make(map[string]int64)
|
||||
for _, result := range results {
|
||||
pvMap[result.NodeID] = result.Count
|
||||
}
|
||||
return pvMap, nil
|
||||
}
|
||||
|
||||
// UpsertNodeStats 插入或更新node_stats表
|
||||
func (r *StatRepository) UpsertNodeStats(ctx context.Context, nodeID string, pvCount int64) error {
|
||||
nodeStats := &domain.NodeStats{
|
||||
NodeID: nodeID,
|
||||
PV: pvCount,
|
||||
}
|
||||
|
||||
// 使用GORM的Clauses进行upsert操作
|
||||
return r.db.WithContext(ctx).
|
||||
Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "node_id"}},
|
||||
DoUpdates: clause.Assignments(map[string]interface{}{
|
||||
"pv": gorm.Expr("node_stats.pv + ?", pvCount),
|
||||
}),
|
||||
}).
|
||||
Create(nodeStats).Error
|
||||
}
|
||||
Reference in New Issue
Block a user