分页查询
This commit is contained in:
9
Makefile
9
Makefile
@@ -9,6 +9,9 @@ dev:
|
|||||||
go run github.com/air-verse/air@latest --build.cmd "go build -o ./data/ bin/main.go" --build.bin "./data/main"; \
|
go run github.com/air-verse/air@latest --build.cmd "go build -o ./data/ bin/main.go" --build.bin "./data/main"; \
|
||||||
wait
|
wait
|
||||||
|
|
||||||
|
link:
|
||||||
|
ssh -NCPf main -L 3306:localhost:3306 -L 19530:localhost:19530
|
||||||
|
|
||||||
# 编译项目
|
# 编译项目
|
||||||
build:
|
build:
|
||||||
go mod tidy
|
go mod tidy
|
||||||
@@ -23,7 +26,7 @@ update: build
|
|||||||
ssh $host "systemctl restart webp"
|
ssh $host "systemctl restart webp"
|
||||||
ssh $host "rm ~/webp/main_old"
|
ssh $host "rm ~/webp/main_old"
|
||||||
|
|
||||||
# 设为系统服务和日志轮转
|
# 设为系统服务和设置日志轮转
|
||||||
service:
|
service:
|
||||||
sudo cp webp.service /etc/systemd/system/webp.service
|
sudo cp webp.service /etc/systemd/system/webp.service
|
||||||
sudo systemctl enable webp
|
sudo systemctl enable webp
|
||||||
@@ -37,3 +40,7 @@ gorse:
|
|||||||
export GORSE_DASHBOARD_USER="gorse"
|
export GORSE_DASHBOARD_USER="gorse"
|
||||||
export GORSE_DASHBOARD_PASS="gorse"
|
export GORSE_DASHBOARD_PASS="gorse"
|
||||||
curl -fsSL https://gorse.io/playground | bash
|
curl -fsSL https://gorse.io/playground | bash
|
||||||
|
|
||||||
|
# 安装搜图服务 python embedding
|
||||||
|
reverse:
|
||||||
|
git clone
|
@@ -1,5 +1,9 @@
|
|||||||
# webp
|
# webp
|
||||||
|
|
||||||
|
- [x] 相似图像推荐(迁移)
|
||||||
|
- [ ] 以图搜图(迁移)
|
||||||
|
- [ ] 标签筛选(补充筛选条件)
|
||||||
|
|
||||||
- [ ] 原始图像
|
- [ ] 原始图像
|
||||||
- [ ] 缩略缓存
|
- [ ] 缩略缓存
|
||||||
|
|
||||||
|
250
api/graphql.go
250
api/graphql.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.satori.love/gameui/webp/models"
|
"git.satori.love/gameui/webp/models"
|
||||||
@@ -11,6 +12,7 @@ import (
|
|||||||
"github.com/graphql-go/graphql/language/ast"
|
"github.com/graphql-go/graphql/language/ast"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
|
"github.com/thoas/go-funk"
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@@ -97,12 +99,13 @@ func NewSchema(config Config) (graphql.Schema, error) {
|
|||||||
Name: "Article",
|
Name: "Article",
|
||||||
Description: "文章",
|
Description: "文章",
|
||||||
Fields: graphql.Fields{
|
Fields: graphql.Fields{
|
||||||
"id": &graphql.Field{Type: graphql.Int, Description: "文章ID"},
|
"id": &graphql.Field{Type: graphql.Int, Description: "ID"},
|
||||||
"title": &graphql.Field{Type: graphql.String, Description: "文章标题"},
|
"title": &graphql.Field{Type: graphql.String, Description: "标题"},
|
||||||
"tags": &graphql.Field{Type: graphql.String, Description: "文章标签"},
|
"orientation": &graphql.Field{Type: graphql.String, Description: "方向"},
|
||||||
"user": &graphql.Field{Type: user, Description: "文章所属用户"},
|
"tags": &graphql.Field{Type: graphql.String, Description: "标签"},
|
||||||
"create_time": &graphql.Field{Type: graphql.DateTime, Description: "文章创建时间"},
|
"user": &graphql.Field{Type: user, Description: "所属用户"},
|
||||||
"update_time": &graphql.Field{Type: graphql.DateTime, Description: "文章更新时间"},
|
"create_time": &graphql.Field{Type: graphql.DateTime, Description: "创建时间"},
|
||||||
|
"update_time": &graphql.Field{Type: graphql.DateTime, Description: "更新时间"},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -167,7 +170,6 @@ func NewSchema(config Config) (graphql.Schema, error) {
|
|||||||
if p.Args["text"] != nil {
|
if p.Args["text"] != nil {
|
||||||
var texts TextList
|
var texts TextList
|
||||||
for _, text := range p.Source.(Image).Text {
|
for _, text := range p.Source.(Image).Text {
|
||||||
fmt.Println("san", text.Text)
|
|
||||||
if strings.Contains(text.Text, p.Args["text"].(string)) {
|
if strings.Contains(text.Text, p.Args["text"].(string)) {
|
||||||
texts = append(texts, text)
|
texts = append(texts, text)
|
||||||
}
|
}
|
||||||
@@ -193,18 +195,6 @@ func NewSchema(config Config) (graphql.Schema, error) {
|
|||||||
for _, field := range fieldAST.SelectionSet.Selections {
|
for _, field := range fieldAST.SelectionSet.Selections {
|
||||||
fieldAST, ok := field.(*ast.Field)
|
fieldAST, ok := field.(*ast.Field)
|
||||||
if ok {
|
if ok {
|
||||||
if fieldAST.Name.Value == "user" {
|
|
||||||
fields = append(fields, "user_id")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fieldAST.Name.Value == "article" {
|
|
||||||
fields = append(fields, "article_id")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fieldAST.Name.Value == "similars" {
|
|
||||||
// 跳过自定义字段
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fields = append(fields, fieldAST.Name.Value)
|
fields = append(fields, fieldAST.Name.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +334,7 @@ func NewSchema(config Config) (graphql.Schema, error) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
Args: graphql.FieldConfigArgument{
|
Args: graphql.FieldConfigArgument{
|
||||||
"preference": &graphql.ArgumentConfig{Type: graphql.String, Description: "使用浏览记录获取的偏好推荐图像"},
|
"interest": &graphql.ArgumentConfig{Type: graphql.Int, Description: "获取指定ID用户的兴趣推荐图像"},
|
||||||
"similar": &graphql.ArgumentConfig{Type: graphql.Int, Description: "获取与指定ID图像相似的图像"},
|
"similar": &graphql.ArgumentConfig{Type: graphql.Int, Description: "获取与指定ID图像相似的图像"},
|
||||||
"id": &graphql.ArgumentConfig{Type: graphql.Int, Description: "获取指定ID的图像"},
|
"id": &graphql.ArgumentConfig{Type: graphql.Int, Description: "获取指定ID的图像"},
|
||||||
"width": &graphql.ArgumentConfig{Type: graphql.Int, Description: "筛选图像中指定宽度的"},
|
"width": &graphql.ArgumentConfig{Type: graphql.Int, Description: "筛选图像中指定宽度的"},
|
||||||
@@ -364,72 +354,49 @@ func NewSchema(config Config) (graphql.Schema, error) {
|
|||||||
"update_time": &graphql.ArgumentConfig{Type: graphql.DateTime, Description: "筛选图像中更新时间等于指定值的"},
|
"update_time": &graphql.ArgumentConfig{Type: graphql.DateTime, Description: "筛选图像中更新时间等于指定值的"},
|
||||||
"first": &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中的前n個元素)"},
|
"first": &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中的前n個元素)"},
|
||||||
"last": &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中的最後n個元素)"},
|
"last": &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中的最後n個元素)"},
|
||||||
"after": &graphql.ArgumentConfig{Type: graphql.String, Description: "翻页参数(傳回清單中指定遊標之後的元素)"},
|
"after": &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中指定遊標之後的元素)"},
|
||||||
"before": &graphql.ArgumentConfig{Type: graphql.String, Description: "翻页参数(傳回清單中指定遊標之前的元素)"},
|
"before": &graphql.ArgumentConfig{Type: graphql.Int, Description: "翻页参数(傳回清單中指定遊標之前的元素)"},
|
||||||
},
|
},
|
||||||
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
|
||||||
// 定义参数结构体
|
// 定义参数结构体
|
||||||
var args struct {
|
var args struct {
|
||||||
First int
|
First int
|
||||||
Last int
|
Last int
|
||||||
After string
|
After int
|
||||||
Before string
|
Before int
|
||||||
Text string
|
Text string
|
||||||
Preference string
|
Interest int
|
||||||
Similar int
|
Similar int
|
||||||
}
|
}
|
||||||
mapstructure.Decode(p.Args, &args)
|
mapstructure.Decode(p.Args, &args)
|
||||||
|
|
||||||
// 参数到 SQL 格式字符串的映射
|
// 限制长度防止全表扫描
|
||||||
var argToSQLFormat = map[string]string{
|
var limit = 10
|
||||||
"id": "id=%d",
|
if args.First != 0 {
|
||||||
"width": "width=%d",
|
limit = args.First
|
||||||
"height": "height=%d",
|
} else if args.Last != 0 {
|
||||||
"content": "content='%s'",
|
limit = args.Last
|
||||||
"remark": "remark='%s'",
|
|
||||||
"description": "description='%s'",
|
|
||||||
"tags": "tags='%s'",
|
|
||||||
"rank": "rank='%s'",
|
|
||||||
"comment_num": "comment_num=%d",
|
|
||||||
"praise_count": "praise_count=%d",
|
|
||||||
"collect_count": "collect_count=%d",
|
|
||||||
"article_id": "article_id=%d",
|
|
||||||
"user_id": "user_id=%d",
|
|
||||||
"create_time": "create_time='%s'",
|
|
||||||
"update_time": "update_time='%s'",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var total int
|
||||||
|
var images []Image
|
||||||
|
var fields = get_fields(p.Info.FieldASTs[0].SelectionSet.Selections)
|
||||||
|
var query = db.Limit(limit)
|
||||||
|
|
||||||
|
// 参数映射
|
||||||
|
var argFormat = []string{"id", "width", "height", "content", "remark", "description", "tags", "rank", "comment_num", "praise_count", "collect_count", "article_id", "user_id", "create_time", "update_time"}
|
||||||
|
|
||||||
// 筛选条件
|
// 筛选条件
|
||||||
var where []string
|
for _, format := range argFormat {
|
||||||
var order []string
|
if p.Args[format] != nil {
|
||||||
for arg, format := range argToSQLFormat {
|
query = query.Where(fmt.Sprintf(format, " = ?"), p.Args[format])
|
||||||
if p.Args[arg] != nil {
|
|
||||||
where = append(where, fmt.Sprintf(format, p.Args[arg]))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var id_list []string
|
var list []int
|
||||||
|
var id_list [][]int
|
||||||
|
|
||||||
// 特殊处理 preference 参数
|
// 筛选:提取文字
|
||||||
if args.Preference != "" {
|
|
||||||
// 去除空格并拆分以逗号分割的ID
|
|
||||||
id_list = strings.Split(strings.ReplaceAll(args.Preference, " ", ""), ",")
|
|
||||||
// 使用这一组 id 推荐
|
|
||||||
fmt.Println("preference:", args.Preference)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 特殊处理 similar 参数
|
|
||||||
if args.Similar != 0 {
|
|
||||||
id_list := models.GetSimilarImagesIdList(args.Similar, 200)
|
|
||||||
ids_str := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(id_list)), ","), "[]")
|
|
||||||
if ids_str == "" {
|
|
||||||
return map[string]interface{}{"list": []Image{}, "total": 0}, nil
|
|
||||||
}
|
|
||||||
where = append(where, fmt.Sprintf("id IN (%s)", ids_str))
|
|
||||||
order = append(order, fmt.Sprintf("ORDER BY FIELD(id,%s)", ids_str))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 特殊处理 text 参数
|
|
||||||
if args.Text != "" {
|
if args.Text != "" {
|
||||||
resp, err := models.ZincSearch(map[string]interface{}{
|
resp, err := models.ZincSearch(map[string]interface{}{
|
||||||
"query": map[string]interface{}{
|
"query": map[string]interface{}{
|
||||||
@@ -447,84 +414,123 @@ func NewSchema(config Config) (graphql.Schema, error) {
|
|||||||
"from": 0,
|
"from": 0,
|
||||||
"size": 200,
|
"size": 200,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("ZincSearch 获取图像列表失败", err)
|
fmt.Println("ZincSearch 获取图像列表失败", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
id_list = resp.ToIDList(args.First, args.Last, args.After, args.Before)
|
|
||||||
id_list_str := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(id_list)), ","), "[]")
|
var item []int
|
||||||
if id_list_str == "" {
|
|
||||||
return map[string]interface{}{
|
for _, hit := range resp.Hits.Hits {
|
||||||
"list": []Image{},
|
num, _ := strconv.Atoi(hit.ID)
|
||||||
"total": 0,
|
item = append(item, num)
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
where = append(where, fmt.Sprintf("id IN (%s)", id_list_str))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
where_str := strings.Join(where, " AND ")
|
id_list = append(id_list, item)
|
||||||
order_str := strings.Join(order, "")
|
|
||||||
|
|
||||||
if where_str != "" {
|
if len(id_list) == 0 {
|
||||||
where_str = "WHERE " + where_str
|
return map[string]interface{}{"list": []Image{}, "total": 0}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理翻页参数
|
// 筛选:相似图像
|
||||||
var limit, offset int
|
if args.Similar != 0 {
|
||||||
if args.First == 0 && args.Last == 0 {
|
var item []int
|
||||||
limit = 10
|
for _, id := range models.GetSimilarImagesIdList(args.Similar, 200) {
|
||||||
offset = 0
|
item = append(item, int(id))
|
||||||
|
}
|
||||||
|
id_list = append(id_list, item)
|
||||||
|
|
||||||
|
if len(id_list) == 0 {
|
||||||
|
return map[string]interface{}{"list": []Image{}, "total": 0}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 筛选:兴趣推荐
|
||||||
|
if args.Interest != 0 {
|
||||||
|
fmt.Println("Interest:", args.Interest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
|
||||||
|
// 截取:取交集
|
||||||
|
if len(id_list) != 0 {
|
||||||
|
list = id_list[0]
|
||||||
|
if len(id_list) > 1 {
|
||||||
|
for _, slice := range id_list[1:] {
|
||||||
|
list = funk.Join(list, slice, funk.InnerJoin).([]int)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(list) == 0 {
|
||||||
|
return map[string]interface{}{"list": []Image{}, "total": 0}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
total = len(list)
|
||||||
|
|
||||||
|
// 截取: 分页
|
||||||
|
if args.After != 0 {
|
||||||
|
index := -1
|
||||||
|
for i, id := range list {
|
||||||
|
if id == args.After {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if index != -1 {
|
||||||
|
list = list[index+1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.Before != 0 {
|
||||||
|
index := -1
|
||||||
|
for i, id := range list {
|
||||||
|
if id == args.Before {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if index != -1 {
|
||||||
|
list = list[:index]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.First != 0 {
|
if args.First != 0 {
|
||||||
limit = args.First
|
list = list[:args.First]
|
||||||
offset = 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.Last != 0 {
|
if args.Last != 0 {
|
||||||
limit = args.Last
|
list = list[len(list)-args.Last:]
|
||||||
offset = len(id_list) - limit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行查询
|
if args.First == 0 && args.Last == 0 {
|
||||||
var query strings.Builder
|
list = list[:10]
|
||||||
fields := strings.Join(get_fields(p.Info.FieldASTs[0].SelectionSet.Selections), ",")
|
}
|
||||||
query.WriteString(fmt.Sprintf("SELECT %s FROM web_images %s %s LIMIT %d OFFSET %d", fields, where_str, order_str, limit, offset))
|
|
||||||
|
|
||||||
var images ImageList
|
// 存在外部筛选条件
|
||||||
var q = query.String()
|
if len(id_list) > 0 && len(list) > 0 {
|
||||||
if err := connection.Select(&images, q); err != nil {
|
query = query.Where("id IN ?", list)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出
|
||||||
|
if funk.Contains(fields, "user") {
|
||||||
|
query = query.Preload("User")
|
||||||
|
fmt.Println("加载 user")
|
||||||
|
}
|
||||||
|
|
||||||
|
if funk.Contains(fields, "article") {
|
||||||
|
query = query.Preload("Article")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := query.Find(&images).Error; err != nil {
|
||||||
fmt.Println("获取图像列表失败", err)
|
fmt.Println("获取图像列表失败", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取用户信息(如果图像列表不为空且请求字段中包含user)
|
|
||||||
if len(images) > 0 && strings.Contains(fields, "user") {
|
|
||||||
user_ids_str := images.ToAllUserID().ToString()
|
|
||||||
var users []User
|
|
||||||
if err := connection.Select(&users, fmt.Sprintf("SELECT id,user_name,avatar,rank,create_time,update_time FROM web_member WHERE id IN (%s)", user_ids_str)); err != nil {
|
|
||||||
fmt.Println("获取用户列表失败", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 将用户信息与图像信息关联
|
|
||||||
images.SetUser(users)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取文章信息(如果图像列表不为空且请求字段中包含article)
|
|
||||||
if len(images) > 0 && strings.Contains(fields, "article") {
|
|
||||||
article_ids_str := images.ToAllArticleID().ToString()
|
|
||||||
var articles []Article
|
|
||||||
if err := connection.Select(&articles, fmt.Sprintf("SELECT id,title,tags,create_time,update_time FROM web_article WHERE id IN (%s)", article_ids_str)); err != nil {
|
|
||||||
fmt.Println("获取文章列表失败", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 将文章信息与图像信息关联
|
|
||||||
images.SetArticle(articles)
|
|
||||||
}
|
|
||||||
|
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"list": images,
|
"list": images,
|
||||||
"total": 0,
|
"total": total,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -55,30 +55,8 @@ func (images *ImageList) ToAllUserID() (uniqueIds IDS) {
|
|||||||
return uniqueIds
|
return uniqueIds
|
||||||
}
|
}
|
||||||
|
|
||||||
// 为每个图像设置用户信息
|
|
||||||
func (images *ImageList) SetUser(userList []User) {
|
|
||||||
for i, image := range *images {
|
|
||||||
for _, user := range userList {
|
|
||||||
if image.UserID == user.ID {
|
|
||||||
(*images)[i].User = user
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为每个图像设置文章信息
|
|
||||||
func (images *ImageList) SetArticle(articleList []Article) {
|
|
||||||
for i, image := range *images {
|
|
||||||
for _, article := range articleList {
|
|
||||||
if image.ArticleID == article.ID {
|
|
||||||
(*images)[i].Article = article
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Image struct {
|
type Image struct {
|
||||||
ID int `json:"id" db:"id"`
|
ID int `json:"id" db:"id" gorm:"primaryKey"`
|
||||||
Width int `json:"width" db:"width"`
|
Width int `json:"width" db:"width"`
|
||||||
Height int `json:"height" db:"height"`
|
Height int `json:"height" db:"height"`
|
||||||
Content string `json:"content" db:"content"`
|
Content string `json:"content" db:"content"`
|
||||||
@@ -93,9 +71,13 @@ type Image struct {
|
|||||||
UserID int `json:"user_id" db:"user_id"`
|
UserID int `json:"user_id" db:"user_id"`
|
||||||
CreateTime time.Time `json:"create_time" db:"create_time"`
|
CreateTime time.Time `json:"create_time" db:"create_time"`
|
||||||
UpdateTime time.Time `json:"update_time" db:"update_time"`
|
UpdateTime time.Time `json:"update_time" db:"update_time"`
|
||||||
Text TextList `json:"text" db:"text"`
|
Text TextList `json:"text" db:"text" gorm:"type:json"`
|
||||||
User User `json:"user" db:"-"`
|
User User `json:"user" gorm:"foreignKey:UserID"`
|
||||||
Article Article `json:"article" db:"-"`
|
Article Article `json:"article" gorm:"foreignKey:ArticleID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Image) TableName() string {
|
||||||
|
return "web_images"
|
||||||
}
|
}
|
||||||
|
|
||||||
type TextList []struct {
|
type TextList []struct {
|
||||||
@@ -109,7 +91,7 @@ func (a *TextList) Scan(value interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int `json:"id" db:"id"`
|
ID int `json:"id" db:"id" gorm:"primaryKey"`
|
||||||
UserName *string `json:"user_name" db:"user_name"`
|
UserName *string `json:"user_name" db:"user_name"`
|
||||||
Avatar *string `json:"avatar" db:"avatar"`
|
Avatar *string `json:"avatar" db:"avatar"`
|
||||||
Rank *string `json:"rank" db:"rank"`
|
Rank *string `json:"rank" db:"rank"`
|
||||||
@@ -117,14 +99,23 @@ type User struct {
|
|||||||
UpdateTime time.Time `json:"update_time" db:"update_time"`
|
UpdateTime time.Time `json:"update_time" db:"update_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (User) TableName() string {
|
||||||
|
return "web_member"
|
||||||
|
}
|
||||||
|
|
||||||
type Article struct {
|
type Article struct {
|
||||||
ID int `json:"id" db:"id"`
|
ID int `json:"id" db:"id" gorm:"primaryKey"`
|
||||||
Title string `json:"title" db:"title"`
|
Title string `json:"title" db:"title"`
|
||||||
|
Orientation string `json:"orientation" db:"orientation"`
|
||||||
Tags string `json:"tags" db:"tags"`
|
Tags string `json:"tags" db:"tags"`
|
||||||
CreateTime time.Time `json:"create_time" db:"create_time"`
|
CreateTime time.Time `json:"create_time" db:"create_time"`
|
||||||
UpdateTime time.Time `json:"update_time" db:"update_time"`
|
UpdateTime time.Time `json:"update_time" db:"update_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Article) TableName() string {
|
||||||
|
return "web_article"
|
||||||
|
}
|
||||||
|
|
||||||
type Category struct {
|
type Category struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
|
2
go.mod
2
go.mod
@@ -51,7 +51,9 @@ require (
|
|||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.4.2 // indirect
|
github.com/subosito/gotenv v1.4.2 // indirect
|
||||||
|
github.com/thoas/go-funk v0.9.3 // indirect
|
||||||
github.com/tjfoc/gmsm v1.3.2 // indirect
|
github.com/tjfoc/gmsm v1.3.2 // indirect
|
||||||
|
github.com/yalue/onnxruntime_go v1.12.1 // indirect
|
||||||
golang.org/x/net v0.28.0 // indirect
|
golang.org/x/net v0.28.0 // indirect
|
||||||
golang.org/x/sys v0.25.0 // indirect
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
golang.org/x/text v0.18.0 // indirect
|
golang.org/x/text v0.18.0 // indirect
|
||||||
|
4
go.sum
4
go.sum
@@ -167,8 +167,12 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
|
|||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||||
|
github.com/thoas/go-funk v0.9.3 h1:7+nAEx3kn5ZJcnDm2Bh23N2yOtweO14bi//dvRtgLpw=
|
||||||
|
github.com/thoas/go-funk v0.9.3/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
|
||||||
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
|
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
|
||||||
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||||
|
github.com/yalue/onnxruntime_go v1.12.1 h1:joCCmBnNjHy04jK9EMP/UV6oPPqySXlRgf3gcUcnI/g=
|
||||||
|
github.com/yalue/onnxruntime_go v1.12.1/go.mod h1:b4X26A8pekNb1ACJ58wAXgNKeUCGEAQ9dmACut9Sm/4=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
@@ -9,6 +9,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -63,13 +64,14 @@ type Response struct {
|
|||||||
} `json:"hits"`
|
} `json:"hits"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (res Response) ToIDList(first, last int, after, before string) (id_list []string) {
|
func (res Response) ToIDList(first, last int, after, before int) (id_list []int) {
|
||||||
for _, hit := range res.Hits.Hits {
|
for _, hit := range res.Hits.Hits {
|
||||||
id_list = append(id_list, hit.ID)
|
num, _ := strconv.Atoi(hit.ID)
|
||||||
|
id_list = append(id_list, num)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果 after 不为 0, 从这个ID开始向后取切片
|
// 如果 after 不为 0, 从这个ID开始向后取切片
|
||||||
if after != "" {
|
if after != 0 {
|
||||||
for i, id := range id_list {
|
for i, id := range id_list {
|
||||||
if id == after {
|
if id == after {
|
||||||
id_list = id_list[i+1:]
|
id_list = id_list[i+1:]
|
||||||
@@ -79,7 +81,7 @@ func (res Response) ToIDList(first, last int, after, before string) (id_list []s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果 before 不为 0, 从这个ID开始向前取切片
|
// 如果 before 不为 0, 从这个ID开始向前取切片
|
||||||
if before != "" {
|
if before != 0 {
|
||||||
for i, id := range id_list {
|
for i, id := range id_list {
|
||||||
if id == before {
|
if id == before {
|
||||||
id_list = id_list[:i]
|
id_list = id_list[:i]
|
||||||
|
Reference in New Issue
Block a user