From 6d10d4e86e2b4ba1a1f9721674889b16e6ecc23c Mon Sep 17 00:00:00 2001 From: satori Date: Fri, 6 Dec 2024 08:25:17 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AD=9B=E9=80=89=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/article.go | 98 +++++++++++++++++++++++++++++++------------------- api/game.go | 4 +-- api/work.go | 95 +++++++++++++++++++++++++++++------------------- 3 files changed, 121 insertions(+), 76 deletions(-) diff --git a/api/article.go b/api/article.go index 09263e3..5793d1e 100644 --- a/api/article.go +++ b/api/article.go @@ -4,10 +4,12 @@ import ( "fmt" "log" "regexp" + "strings" "time" "github.com/doug-martin/goqu/v9" "github.com/graphql-go/graphql" + "github.com/thoas/go-funk" ) type Article struct { @@ -19,6 +21,8 @@ type Article struct { Tags string `json:"tags" db:"tags"` UserId int `json:"user_id" db:"user_id"` User User `json:"user" gorm:"foreignKey:UserId"` + Collect bool `json:"collect" gorm:"column:is_collect"` + Praise bool `json:"praise" gorm:"column:is_praise"` CollectCount int `json:"collect_count" gorm:"column:collect_num"` PraiseCount int `json:"praise_count" gorm:"column:praise_num"` CreateTime time.Time `json:"create_time" db:"create_time"` @@ -42,34 +46,10 @@ var articleType = graphql.NewObject(graphql.ObjectConfig{ "user": &graphql.Field{Type: userType, Description: "所属用户"}, "create_time": &graphql.Field{Type: graphql.DateTime, Description: "创建时间"}, "update_time": &graphql.Field{Type: graphql.DateTime, Description: "更新时间"}, + "praise": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否点赞"}, + "collect": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否收藏"}, "praise_count": &graphql.Field{Type: graphql.Int, Description: "点赞数"}, "collect_count": &graphql.Field{Type: graphql.Int, Description: "收藏数"}, - "praise": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否点赞", Resolve: func(p graphql.ResolveParams) (interface{}, error) { - var user_id = p.Context.Value("user_id").(int) - if user_id != 0 { - var praise int64 - if err := db.Table("web_praise").Where("user_id = ?", user_id).Where("praise_id = ?", p.Source.(Article).ID).Where("type = ?", 0).Count(&praise); err != nil { - return false, nil - } - if praise > 0 { - return true, nil - } - } - return false, nil - }}, - "collect": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否收藏", Resolve: func(p graphql.ResolveParams) (interface{}, error) { - var user_id = p.Context.Value("user_id").(int) - if user_id != 0 { - var collect int64 - if err := db.Table("web_collect").Where("user_id = ?", user_id).Where("collect_id = ?", p.Source.(Article).ID).Where("type = ?", 0).Count(&collect); err != nil { - return false, nil - } - if collect > 0 { - return true, nil - } - } - return false, nil - }}, }, }) @@ -129,13 +109,30 @@ var ArticleItems = &graphql.Field{ } } - // 排序条件 - if p.Args["sort"] != nil { - if p.Args["order"].(string) == "ASC" { - query = query.Order(goqu.C(p.Args["sort"].(string)).Asc()) - } - if p.Args["order"].(string) == "DESC" { - query = query.Order(goqu.C(p.Args["sort"].(string)).Desc()) + // 按指定用户点赞筛选 + if p.Args["praise"] != nil { + query = query.Join(goqu.T("web_praise"), goqu.On( + goqu.I("web_article.id").Eq(goqu.I("web_praise.praise_id")), + goqu.I("web_praise.user_id").Eq(p.Args["praise"]), + goqu.I("web_praise.type").Eq(0), + )) + } + + // 按指定用户收藏筛选 + if p.Args["collect"] != nil { + query = query.Join(goqu.T("web_collect"), goqu.On( + goqu.I("web_article.id").Eq(goqu.I("web_collect.collect_id")), + goqu.I("web_collect.user_id").Eq(p.Args["collect"]), + goqu.I("web_collect.type").Eq(0), + )) + } + + // 如果查询了 total 字段 + if existField(p.Info.FieldASTs[0].SelectionSet.Selections, "total") { + sql, _, _ := query.ToSQL() + sql = strings.Replace(sql, "SELECT *", "SELECT COUNT(*)", 1) + if err := db.Raw(sql).Scan(&total).Error; err != nil { + return nil, err } } @@ -145,11 +142,20 @@ var ArticleItems = &graphql.Field{ query = query.Select("web_article.id", goqu.L( fmt.Sprintf("ROW_NUMBER() OVER(ORDER BY web_article.%s %s)", sort, p.Args["order"]), ).As("row_num")) + } else { + // 排序条件 + if p.Args["sort"] != nil { + if p.Args["order"].(string) == "ASC" { + query = query.Order(goqu.C(p.Args["sort"].(string)).Asc()) + } + if p.Args["order"].(string) == "DESC" { + query = query.Order(goqu.C(p.Args["sort"].(string)).Desc()) + } + } } // 取所有数据的前N条 sql, _, _ := query.ToSQL() - fmt.Println(sql) // 遊標截取篩選結果集的前N条 var cursor string @@ -164,13 +170,31 @@ var ArticleItems = &graphql.Field{ limit = p.Args["last"].(int) } + // 字段选择 + var user_id = p.Context.Value("user_id").(int) + var fields = ListItem(p.Info.FieldASTs[0].SelectionSet.Selections) + var praise, praise_join, collect, collect_join, text_count string + if funk.Contains(fields, "praise") { + praise = ",CASE WHEN web_praise.id IS NOT NULL THEN TRUE ELSE FALSE END AS is_praise" + praise_join = fmt.Sprintf("LEFT JOIN web_praise ON web_praise.praise_id = web_article.id AND web_praise.user_id = %d AND web_praise.type = 0", user_id) + } + if funk.Contains(fields, "collect") { + collect = ",CASE WHEN web_collect.id IS NOT NULL THEN TRUE ELSE FALSE END AS is_collect" + collect_join = fmt.Sprintf("LEFT JOIN web_collect ON web_collect.collect_id = web_article.id AND web_collect.user_id = %d AND web_collect.type = 0", user_id) + } + if funk.Contains(fields, "text_count") { + text_count = ",(SELECT COUNT(*) FROM web_images wi WHERE wi.article_id = web_article.id AND wi.text != '') AS text_count" + } + sql = fmt.Sprintf(` WITH RankedArticles AS (%s) - SELECT * FROM web_article INNER JOIN( + SELECT * %s %s %s FROM web_article INNER JOIN( SELECT id, row_num FROM RankedArticles %s - ) AS LimitedRanked ON LimitedRanked.id = web_article.id + ) AS LimitedRanked ON LimitedRanked.id = web_article.id %s %s ORDER BY LimitedRanked.row_num ASC LIMIT %d - `, sql, cursor, limit) + `, sql, praise, collect, text_count, cursor, praise_join, collect_join, limit) + + fmt.Println(sql) if err := db.Raw(sql).Scan(&articles).Error; err != nil { fmt.Println("获取游戏列表失败", err) diff --git a/api/game.go b/api/game.go index 234367f..5ea2ee1 100644 --- a/api/game.go +++ b/api/game.go @@ -46,10 +46,10 @@ var gameType = graphql.NewObject(graphql.ObjectConfig{ "era": &graphql.Field{Type: graphql.String, Description: "游戏上线年份"}, "create_time": &graphql.Field{Type: graphql.DateTime, Description: "游戏创建时间"}, "update_time": &graphql.Field{Type: graphql.DateTime, Description: "游戏更新时间"}, - "praise_count": &graphql.Field{Type: graphql.Int, Description: "点赞数"}, - "collect_count": &graphql.Field{Type: graphql.Int, Description: "收藏数"}, "praise": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否点赞"}, "collect": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否收藏"}, + "praise_count": &graphql.Field{Type: graphql.Int, Description: "点赞数"}, + "collect_count": &graphql.Field{Type: graphql.Int, Description: "收藏数"}, "text_count": &graphql.Field{Type: graphql.Int, Description: "文字数量"}, }, }) diff --git a/api/work.go b/api/work.go index 1544658..889cf0a 100644 --- a/api/work.go +++ b/api/work.go @@ -3,10 +3,12 @@ package api import ( "fmt" "regexp" + "strings" "time" "github.com/doug-martin/goqu/v9" "github.com/graphql-go/graphql" + "github.com/thoas/go-funk" ) type Work struct { @@ -21,6 +23,8 @@ type Work struct { Image string `json:"image"` Images string `json:"images"` User User `json:"user" gorm:"foreignKey:UserId"` + Collect bool `json:"collect" gorm:"column:is_collect"` + Praise bool `json:"praise" gorm:"column:is_praise"` CollectCount int `json:"collect_count" gorm:"column:collect_num"` PraiseCount int `json:"praise_count" gorm:"column:praise_num"` CreateTime time.Time `json:"create_time"` @@ -39,34 +43,10 @@ var workType = graphql.NewObject(graphql.ObjectConfig{ "title": &graphql.Field{Type: graphql.String, Description: "作品标题"}, "create_time": &graphql.Field{Type: graphql.DateTime, Description: "作品创建时间"}, "update_time": &graphql.Field{Type: graphql.DateTime, Description: "作品更新时间"}, + "praise": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否点赞"}, + "collect": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否收藏"}, "praise_count": &graphql.Field{Type: graphql.Int, Description: "点赞数"}, "collect_count": &graphql.Field{Type: graphql.Int, Description: "收藏数"}, - "praise": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否点赞", Resolve: func(p graphql.ResolveParams) (interface{}, error) { - var user_id = p.Context.Value("user_id").(int) - if user_id != 0 { - var praise int64 - if err := db.Table("web_praise").Where("user_id = ?", user_id).Where("praise_id = ?", p.Source.(Work).ID).Where("type = ?", 0).Count(&praise); err != nil { - return false, nil - } - if praise > 0 { - return true, nil - } - } - return false, nil - }}, - "collect": &graphql.Field{Type: graphql.Boolean, Description: "当前用户是否收藏", Resolve: func(p graphql.ResolveParams) (interface{}, error) { - var user_id = p.Context.Value("user_id").(int) - if user_id != 0 { - var collect int64 - if err := db.Table("web_collect").Where("user_id = ?", user_id).Where("collect_id = ?", p.Source.(Work).ID).Where("type = ?", 0).Count(&collect); err != nil { - return false, nil - } - if collect > 0 { - return true, nil - } - } - return false, nil - }}, }, }) @@ -108,13 +88,30 @@ var WorkItems = &graphql.Field{ } } - // 排序条件 - if p.Args["sort"] != nil { - if p.Args["order"].(string) == "ASC" { - query = query.Order(goqu.C(p.Args["sort"].(string)).Asc()) - } - if p.Args["order"].(string) == "DESC" { - query = query.Order(goqu.C(p.Args["sort"].(string)).Desc()) + // 按指定用户点赞筛选 + if p.Args["praise"] != nil { + query = query.Join(goqu.T("web_praise"), goqu.On( + goqu.I("web_article.id").Eq(goqu.I("web_praise.praise_id")), + goqu.I("web_praise.user_id").Eq(p.Args["praise"]), + goqu.I("web_praise.type").Eq(0), + )) + } + + // 按指定用户收藏筛选 + if p.Args["collect"] != nil { + query = query.Join(goqu.T("web_collect"), goqu.On( + goqu.I("web_article.id").Eq(goqu.I("web_collect.collect_id")), + goqu.I("web_collect.user_id").Eq(p.Args["collect"]), + goqu.I("web_collect.type").Eq(0), + )) + } + + // 如果查询了 total 字段 + if existField(p.Info.FieldASTs[0].SelectionSet.Selections, "total") { + sql, _, _ := query.ToSQL() + sql = strings.Replace(sql, "SELECT *", "SELECT COUNT(*)", 1) + if err := db.Raw(sql).Scan(&total).Error; err != nil { + return nil, err } } @@ -124,11 +121,20 @@ var WorkItems = &graphql.Field{ query = query.Select("web_article.id", goqu.L( fmt.Sprintf("ROW_NUMBER() OVER(ORDER BY web_article.%s %s)", sort, p.Args["order"]), ).As("row_num")) + } else { + // 排序条件 + if p.Args["sort"] != nil { + if p.Args["order"].(string) == "ASC" { + query = query.Order(goqu.C(p.Args["sort"].(string)).Asc()) + } + if p.Args["order"].(string) == "DESC" { + query = query.Order(goqu.C(p.Args["sort"].(string)).Desc()) + } + } } // 取所有数据的前N条 sql, _, _ := query.ToSQL() - fmt.Println(sql) // 遊標截取篩選結果集的前N条 var cursor string @@ -143,13 +149,28 @@ var WorkItems = &graphql.Field{ limit = p.Args["last"].(int) } + // 字段选择 + var user_id = p.Context.Value("user_id").(int) + var fields = ListItem(p.Info.FieldASTs[0].SelectionSet.Selections) + var praise, praise_join, collect, collect_join, text_count string + if funk.Contains(fields, "praise") { + praise = ",CASE WHEN web_praise.id IS NOT NULL THEN TRUE ELSE FALSE END AS is_praise" + praise_join = fmt.Sprintf("LEFT JOIN web_praise ON web_praise.praise_id = web_article.id AND web_praise.user_id = %d AND web_praise.type = 0", user_id) + } + if funk.Contains(fields, "collect") { + collect = ",CASE WHEN web_collect.id IS NOT NULL THEN TRUE ELSE FALSE END AS is_collect" + collect_join = fmt.Sprintf("LEFT JOIN web_collect ON web_collect.collect_id = web_article.id AND web_collect.user_id = %d AND web_collect.type = 0", user_id) + } + sql = fmt.Sprintf(` WITH RankedArticles AS (%s) - SELECT * FROM web_article INNER JOIN( + SELECT * %s %s %s FROM web_article INNER JOIN( SELECT id, row_num FROM RankedArticles %s - ) AS LimitedRanked ON LimitedRanked.id = web_article.id + ) AS LimitedRanked ON LimitedRanked.id = web_article.id %s %s ORDER BY LimitedRanked.row_num ASC LIMIT %d - `, sql, cursor, limit) + `, sql, praise, collect, text_count, cursor, praise_join, collect_join, limit) + + fmt.Println(sql) if err := db.Raw(sql).Scan(&works).Error; err != nil { fmt.Println("获取游戏列表失败", err)