From bcfde1999c9ec0dffd740c0cc85f230cd0a5cd52 Mon Sep 17 00:00:00 2001 From: satori Date: Wed, 27 Nov 2024 20:26:18 +0800 Subject: [PATCH] works --- api/graphql.go | 245 +++++++++++++++++++++++++++++++++++++++---------- api/struct.go | 20 ++++ 2 files changed, 216 insertions(+), 49 deletions(-) diff --git a/api/graphql.go b/api/graphql.go index 755e076..d926a2f 100644 --- a/api/graphql.go +++ b/api/graphql.go @@ -569,6 +569,24 @@ func NewSchema(config Config) (graphql.Schema, error) { } } + // 如果没有外部排序则使用指定排序(正则sort只能是字母数字下划下) + if p.Args["text"] == nil && p.Args["similar"] == nil && p.Args["interest"] == nil { + sort := regexp.MustCompile(`[^a-zA-Z0-9_]`).ReplaceAllString(p.Args["sort"].(string), "") + query = query.Select("web_images.id", goqu.L( + fmt.Sprintf("ROW_NUMBER() OVER(ORDER BY web_images.%s %s)", sort, p.Args["order"]), + ).As("row_num")) + } + + // 取所有数据的前N条 + sql, _, _ := query.Where(goqu.Ex{"article_category_top_id": 22}).ToSQL() + fmt.Println(sql) + + // 遊標截取篩選結果集的前N条 + var cursor string + if p.Args["after"] != nil { + cursor = fmt.Sprintf(`WHERE row_num > (SELECT row_num FROM RankedArticles WHERE RankedArticles.id = %d)`, p.Args["after"].(int)) + } + var limit int = 10 if p.Args["first"] != nil { limit = p.Args["first"].(int) @@ -576,6 +594,14 @@ func NewSchema(config Config) (graphql.Schema, error) { limit = p.Args["last"].(int) } + sql = fmt.Sprintf(` + WITH RankedArticles AS (%s) + SELECT * FROM web_images INNER JOIN( + SELECT id, row_num FROM RankedArticles %s + ) AS LimitedRanked ON LimitedRanked.id = web_images.id + ORDER BY LimitedRanked.row_num ASC LIMIT %d + `, sql, cursor, limit) + if err := db.Limit(limit).Where("category_top_id = 22").Find(&games).Error; err != nil { return nil, err } @@ -586,6 +612,176 @@ func NewSchema(config Config) (graphql.Schema, error) { }, err }, }, + "works": &graphql.Field{ + Name: "works", + Description: "作品列表", + Type: graphql.NewObject(graphql.ObjectConfig{ + Name: "WorkConnection", + Description: "条件筛选作品列表", + Fields: graphql.Fields{ + "list": &graphql.Field{Type: graphql.NewList(article), Description: "作品列表"}, + //"total": &graphql.Field{Type: graphql.Int, Description: "作品总数"}, + }, + }), + Args: graphql.FieldConfigArgument{ + "id": &graphql.ArgumentConfig{Type: graphql.Int, Description: "筛选作品中指定ID的"}, + "title": &graphql.ArgumentConfig{Type: graphql.String, Description: "筛选作品中含有指定标题的"}, + "tags": &graphql.ArgumentConfig{Type: graphql.String, Description: "筛选作品中含有指定标签的"}, + "create_time": &graphql.ArgumentConfig{Type: graphql.DateTime, Description: "筛选作品中创建时间等于指定值的"}, + "update_time": &graphql.ArgumentConfig{Type: graphql.DateTime, Description: "筛选作品中更新时间等于指定值的"}, + }, + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + var works []Work + var total int + var err error + + var query = goqu.Dialect("mysql").From("web_article") + + // 筛选条件 + for _, format := range []string{"id", "style", "device", "orientation", "era", "category_id", "tags"} { + if p.Args[format] != nil { + query = query.Where(goqu.C(format).Eq(p.Args[format])) + } + } + + // 排序条件 + 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()) + } + } + + // 如果没有外部排序则使用指定排序(正则sort只能是字母数字下划下) + if p.Args["text"] == nil && p.Args["similar"] == nil && p.Args["interest"] == nil { + sort := regexp.MustCompile(`[^a-zA-Z0-9_]`).ReplaceAllString(p.Args["sort"].(string), "") + query = query.Select("web_images.id", goqu.L( + fmt.Sprintf("ROW_NUMBER() OVER(ORDER BY web_images.%s %s)", sort, p.Args["order"]), + ).As("row_num")) + } + + // 取所有数据的前N条 + sql, _, _ := query.Where(goqu.Ex{"article_category_top_id": 1}).ToSQL() + fmt.Println(sql) + + // 遊標截取篩選結果集的前N条 + var cursor string + if p.Args["after"] != nil { + cursor = fmt.Sprintf(`WHERE row_num > (SELECT row_num FROM RankedArticles WHERE RankedArticles.id = %d)`, p.Args["after"].(int)) + } + + var limit int = 10 + if p.Args["first"] != nil { + limit = p.Args["first"].(int) + } else if p.Args["last"] != nil { + limit = p.Args["last"].(int) + } + + sql = fmt.Sprintf(` + WITH RankedArticles AS (%s) + SELECT * FROM web_images INNER JOIN( + SELECT id, row_num FROM RankedArticles %s + ) AS LimitedRanked ON LimitedRanked.id = web_images.id + ORDER BY LimitedRanked.row_num ASC LIMIT %d + `, sql, cursor, limit) + + if err := db.Limit(limit).Where("category_top_id = 1").Find(&works).Error; err != nil { + return nil, err + } + + return map[string]interface{}{ + "list": works, + "total": total, + }, err + }, + }, + "articles": &graphql.Field{ + Name: "articles", + Description: "文章列表", + Type: graphql.NewObject(graphql.ObjectConfig{ + Name: "ArticleConnection", + Description: "条件筛选文章列表", + Fields: graphql.Fields{ + "list": &graphql.Field{Type: graphql.NewList(article), Description: "文章列表"}, + "total": &graphql.Field{Type: graphql.Int, Description: "文章总数"}, + }, + }), + Args: graphql.FieldConfigArgument{ + "id": &graphql.ArgumentConfig{Type: graphql.Int, Description: "筛选文章中指定ID的"}, + "title": &graphql.ArgumentConfig{Type: graphql.String, Description: "筛选文章中含有指定标题的"}, + "tags": &graphql.ArgumentConfig{Type: graphql.String, Description: "筛选文章中含有指定标签的"}, + "create_time": &graphql.ArgumentConfig{Type: graphql.DateTime, Description: "筛选文章中创建时间等于指定值的"}, + "update_time": &graphql.ArgumentConfig{Type: graphql.DateTime, Description: "筛选文章中更新时间等于指定值的"}, + }, + Resolve: func(p graphql.ResolveParams) (interface{}, error) { + var articles []Article + var total int + var err error + + var query = goqu.Dialect("mysql").From("web_article") + + // 筛选条件 + for _, format := range []string{"id", "style", "device", "orientation", "era", "category_id", "tags"} { + if p.Args[format] != nil { + query = query.Where(goqu.C(format).Eq(p.Args[format])) + } + } + + // 排序条件 + 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()) + } + } + + // 如果没有外部排序则使用指定排序(正则sort只能是字母数字下划下) + if p.Args["text"] == nil && p.Args["similar"] == nil && p.Args["interest"] == nil { + sort := regexp.MustCompile(`[^a-zA-Z0-9_]`).ReplaceAllString(p.Args["sort"].(string), "") + query = query.Select("web_images.id", goqu.L( + fmt.Sprintf("ROW_NUMBER() OVER(ORDER BY web_images.%s %s)", sort, p.Args["order"]), + ).As("row_num")) + } + + // 取所有数据的前N条 + sql, _, _ := query.Where(goqu.Ex{"article_category_top_id": 9}).ToSQL() + fmt.Println(sql) + + // 遊標截取篩選結果集的前N条 + var cursor string + if p.Args["after"] != nil { + cursor = fmt.Sprintf(`WHERE row_num > (SELECT row_num FROM RankedArticles WHERE RankedArticles.id = %d)`, p.Args["after"].(int)) + } + + var limit int = 10 + if p.Args["first"] != nil { + limit = p.Args["first"].(int) + } else if p.Args["last"] != nil { + limit = p.Args["last"].(int) + } + + sql = fmt.Sprintf(` + WITH RankedArticles AS (%s) + SELECT * FROM web_images INNER JOIN( + SELECT id, row_num FROM RankedArticles %s + ) AS LimitedRanked ON LimitedRanked.id = web_images.id + ORDER BY LimitedRanked.row_num ASC LIMIT %d + `, sql, cursor, limit) + + if err := db.Limit(limit).Where("category_top_id = 9").Find(&articles).Error; err != nil { + return nil, err + } + + return map[string]interface{}{ + "list": articles, + "total": total, + }, err + }, + }, "images": &graphql.Field{ Name: "images", Description: "图像列表", @@ -1017,55 +1213,6 @@ func NewSchema(config Config) (graphql.Schema, error) { }, nil }, }, - "articles": &graphql.Field{ - Name: "Articles", - Description: "文章列表", - Type: graphql.NewObject(graphql.ObjectConfig{ - Name: "ArticleConnection", - Description: "条件筛选文章列表", - Fields: graphql.Fields{ - "list": &graphql.Field{Type: graphql.NewList(article), Description: "文章列表"}, - "total": &graphql.Field{Type: graphql.Int, Description: "文章总数"}, - }, - }), - Args: graphql.FieldConfigArgument{ - "id": &graphql.ArgumentConfig{Type: graphql.Int, Description: "筛选文章中指定ID的"}, - "title": &graphql.ArgumentConfig{Type: graphql.String, Description: "筛选文章中含有指定标题的"}, - "tags": &graphql.ArgumentConfig{Type: graphql.String, Description: "筛选文章中含有指定标签的"}, - "create_time": &graphql.ArgumentConfig{Type: graphql.DateTime, Description: "筛选文章中创建时间等于指定值的"}, - "update_time": &graphql.ArgumentConfig{Type: graphql.DateTime, Description: "筛选文章中更新时间等于指定值的"}, - }, - Resolve: func(p graphql.ResolveParams) (interface{}, error) { - first := 10 // p.Args["first"] - after := 0 // p.Args["after"] - fields := strings.Join(get_fields(p.Info.FieldASTs[0].SelectionSet.Selections), ",") - var where []string - if p.Args["id"] != nil { - where = append(where, fmt.Sprintf("id=%d", p.Args["id"])) - } - if p.Args["title"] != nil { - where = append(where, fmt.Sprintf("title='%s'", p.Args["title"])) - } - // 筛选条件 - where_str := strings.Join(where, " AND ") - if where_str != "" { - where_str = "WHERE " + where_str - } - - var query strings.Builder - query.WriteString(fmt.Sprintf("SELECT %s FROM web_article %s LIMIT %d OFFSET %d", fields, where_str, first, after)) - // 返回翻页信息 - var articles []Article - if err := connection.Select(&articles, query.String()); err != nil { - fmt.Println("获取文章列表失败", err) - return nil, err - } - return map[string]interface{}{ - "list": articles, - "total": 0, - }, nil - }, - }, "tags": &graphql.Field{ Name: "tags", Description: "标签列表", diff --git a/api/struct.go b/api/struct.go index 426f029..4917310 100644 --- a/api/struct.go +++ b/api/struct.go @@ -109,6 +109,26 @@ func (User) TableName() string { return "web_member" } +type Work struct { + ID int `json:"id" gorm:"primaryKey"` + Title string `json:"title"` + Orientation string `json:"orientation"` + Device string `json:"device"` + Era string `json:"era"` + Tags string `json:"tags"` + UserId int `json:"user_id"` + Content string `json:"content"` + Image string `json:"image"` + Images string `json:"images"` + User User `json:"user" gorm:"foreignKey:UserId"` + CreateTime time.Time `json:"create_time"` + UpdateTime time.Time `json:"update_time"` +} + +func (Work) TableName() string { + return "web_article" +} + type Game struct { ID int `json:"id" gorm:"primaryKey"` Title string `json:"title"`