psi api
This commit is contained in:
parent
7f14b6cf53
commit
ec6e27e023
294
es/es_search.go
294
es/es_search.go
@ -70,6 +70,49 @@ type ESBookResponse struct {
|
|||||||
Other map[string]interface{} `json:"other"` // 扩展字段,用于兼容未来新增字段
|
Other map[string]interface{} `json:"other"` // 扩展字段,用于兼容未来新增字段
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ESBookResponseByPSI 用于返回给Java客户端的格式,ID为简单的int64
|
||||||
|
type ESBookResponseByPSI struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
BookName string `json:"book_name"`
|
||||||
|
BookPic map[string]interface{} `json:"book_pic"`
|
||||||
|
BookPicS map[string]interface{} `json:"book_pic_s"`
|
||||||
|
BookPicB string `json:"book_pic_b"`
|
||||||
|
BookPicW map[string]interface{} `json:"book_pic_w"`
|
||||||
|
BookDefPic map[string]interface{} `json:"book_def_pic"` // 自制官图,临时用
|
||||||
|
ISBN string `json:"isbn"`
|
||||||
|
Author string `json:"author"`
|
||||||
|
Category string `json:"category"`
|
||||||
|
Publisher string `json:"publisher"`
|
||||||
|
PublicationTime string `json:"publication_time"`
|
||||||
|
BindingLayout string `json:"binding_layout"`
|
||||||
|
FixPrice float64 `json:"fix_price"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
IsSuit int `json:"is_suit"`
|
||||||
|
DaySale7 int `json:"day_sale_7"`
|
||||||
|
DaySale15 int `json:"day_sale_15"`
|
||||||
|
DaySale30 int `json:"day_sale_30"`
|
||||||
|
DaySale60 int `json:"day_sale_60"`
|
||||||
|
DaySale90 int `json:"day_sale_90"`
|
||||||
|
DaySale180 int `json:"day_sale_180"`
|
||||||
|
DaySale365 int `json:"day_sale_365"`
|
||||||
|
ThisYearSale int `json:"this_year_sale"`
|
||||||
|
LastYearSale int `json:"last_year_sale"`
|
||||||
|
TotalSale int `json:"total_sale"`
|
||||||
|
BuyCounts int64 `json:"buy_counts"`
|
||||||
|
SellCounts int64 `json:"sell_counts"`
|
||||||
|
BookPicObj map[string]interface{} `json:"book_pic_obj"`
|
||||||
|
BookPicObjS map[string]interface{} `json:"book_pic_obj_s"`
|
||||||
|
UpdateTime NumberOrString `json:"update_time"`
|
||||||
|
IsIllegal int `json:"is_illegal"` // 是否非法 示例 000000
|
||||||
|
IsReturn int `json:"is_return"` // 是否为驳回 示例 0 否 1 是
|
||||||
|
IsFilter string `json:"is_filter"` // 过滤字段
|
||||||
|
PageCount NumberOrString `json:"page_count"` // 页数
|
||||||
|
WordCount NumberOrString `json:"word_count"` // 字数
|
||||||
|
BookFormat NumberOrString `json:"book_format"` // 多少开
|
||||||
|
CatId request.CatIdObject `json:"cat_id"` // 类目
|
||||||
|
Other map[string]interface{} `json:"other"` // 扩展字段,用于兼容未来新增字段
|
||||||
|
}
|
||||||
|
|
||||||
// FlexibleString 处理可能是字符串或数组的字段
|
// FlexibleString 处理可能是字符串或数组的字段
|
||||||
type FlexibleString struct {
|
type FlexibleString struct {
|
||||||
Value string
|
Value string
|
||||||
@ -210,6 +253,71 @@ func (book *ESBook) ConvertToResponse() ESBookResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConvertToResponseByPsi 将ESBook转换为ESBookResponse,处理ID字段转换
|
||||||
|
func (book *ESBook) ConvertToResponseByPsi() ESBookResponseByPSI {
|
||||||
|
bookPicMap := map[string]interface{}{
|
||||||
|
"localPath": book.BookPic.LocalPath,
|
||||||
|
"pddPath": book.BookPic.PddPath,
|
||||||
|
}
|
||||||
|
bookPicSMap := map[string]interface{}{
|
||||||
|
"localPath": book.BookPicS.LocalPath,
|
||||||
|
"pddResponse": book.BookPicS.PddResponse,
|
||||||
|
}
|
||||||
|
bookDefPic := map[string]interface{}{
|
||||||
|
"localPath": book.BookDefPic.LocalPath,
|
||||||
|
"pddPath": book.BookDefPic.PddPath,
|
||||||
|
}
|
||||||
|
publicationTime := book.PublicationTime
|
||||||
|
if publicationTime == "" || publicationTime == "0" || publicationTime == "0000-00-00" {
|
||||||
|
publicationTime = time.Unix(0, 0).Format("2006-01")
|
||||||
|
} else {
|
||||||
|
if timeVal, err := strconv.ParseInt(publicationTime, 10, 64); err == nil {
|
||||||
|
publicationTime = strconv.FormatInt(timeVal-5364000000, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESBookResponseByPSI{
|
||||||
|
ID: book.ID,
|
||||||
|
BookName: book.BookName.Value,
|
||||||
|
BookPic: bookPicMap,
|
||||||
|
BookPicS: bookPicSMap,
|
||||||
|
BookPicB: book.BookPicB,
|
||||||
|
BookPicW: book.BookPicW,
|
||||||
|
BookDefPic: bookDefPic,
|
||||||
|
ISBN: book.ISBN,
|
||||||
|
Author: book.Author,
|
||||||
|
Category: book.Category,
|
||||||
|
Publisher: book.Publisher,
|
||||||
|
PublicationTime: publicationTime,
|
||||||
|
BindingLayout: book.BindingLayout,
|
||||||
|
FixPrice: float64(book.FixPrice),
|
||||||
|
Content: book.Content,
|
||||||
|
IsSuit: book.IsSuit,
|
||||||
|
DaySale7: book.DaySale7,
|
||||||
|
DaySale15: book.DaySale15,
|
||||||
|
DaySale30: book.DaySale30,
|
||||||
|
DaySale60: book.DaySale60,
|
||||||
|
DaySale90: book.DaySale90,
|
||||||
|
DaySale180: book.DaySale180,
|
||||||
|
DaySale365: book.DaySale365,
|
||||||
|
ThisYearSale: book.ThisYearSale,
|
||||||
|
LastYearSale: book.LastYearSale,
|
||||||
|
TotalSale: book.TotalSale,
|
||||||
|
BuyCounts: book.BuyCounts,
|
||||||
|
SellCounts: book.SellCounts,
|
||||||
|
BookPicObj: book.BookPicObj,
|
||||||
|
BookPicObjS: book.BookPicObjS,
|
||||||
|
UpdateTime: book.UpdateTime,
|
||||||
|
IsIllegal: book.IsIllegal,
|
||||||
|
IsReturn: book.IsReturn,
|
||||||
|
IsFilter: book.IsFilter,
|
||||||
|
PageCount: book.PageCount,
|
||||||
|
WordCount: book.WordCount,
|
||||||
|
BookFormat: book.BookFormat,
|
||||||
|
CatId: book.CatId,
|
||||||
|
Other: book.Other,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 用于 book_pic
|
// 用于 book_pic
|
||||||
type BookPicObj struct {
|
type BookPicObj struct {
|
||||||
LocalPath string `json:"localPath"`
|
LocalPath string `json:"localPath"`
|
||||||
@ -322,8 +430,10 @@ type AddBookFullRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ESSearchService struct {
|
type ESSearchService struct {
|
||||||
ES *ESClient
|
ES *ESClient
|
||||||
|
SyncRedisByISBN func(isbn string, act string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type NumberOrString string
|
type NumberOrString string
|
||||||
|
|
||||||
func (n *NumberOrString) UnmarshalJSON(data []byte) error {
|
func (n *NumberOrString) UnmarshalJSON(data []byte) error {
|
||||||
@ -2344,6 +2454,110 @@ func (svc *ESSearchService) SearchBookByISBNHandler(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *ESSearchService) SearchBookByISBNHandlerToPsi(c *gin.Context) {
|
||||||
|
isbn := c.Query("isbn")
|
||||||
|
if isbn == "" {
|
||||||
|
log.Printf("[SearchBookByISBNHandler] 缺少 isbn 参数")
|
||||||
|
c.JSON(400, gin.H{"error": "缺少 isbn 参数"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[SearchBookByISBNHandler] 查询 ISBN: %s", isbn)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
endpoint := c.FullPath()
|
||||||
|
|
||||||
|
// Redis 查询(使用监控)
|
||||||
|
db1Client, err := redisClient.GetClientByName("db1")
|
||||||
|
if err == nil {
|
||||||
|
monitoredRedis := monitor.NewMonitoredRedisClient(db1Client, endpoint)
|
||||||
|
val, _, err := monitoredRedis.Get(ctx, isbn)
|
||||||
|
if err == nil && val != "" {
|
||||||
|
log.Printf("[SearchBookByISBNHandler] 从 Redis db1 查询到数据:%s", isbn)
|
||||||
|
var redisBook request.BookInfoByPsi
|
||||||
|
if err := json.Unmarshal([]byte(val), &redisBook); err == nil {
|
||||||
|
esBook := ConvertRedisBookToESBookByPsi(&redisBook)
|
||||||
|
if esBook != nil {
|
||||||
|
responseData := esBook.ConvertToResponseByPsi()
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
"data": responseData,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("[SearchBookByISBNHandler] Redis 数据解析失败:%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES 查询(使用监控)
|
||||||
|
query := map[string]interface{}{
|
||||||
|
"query": map[string]interface{}{
|
||||||
|
"term": map[string]interface{}{
|
||||||
|
"isbn": isbn,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"_source": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := json.Marshal(query)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[SearchBookByISBNHandler] 构建查询 JSON 失败:%v", err)
|
||||||
|
c.JSON(500, gin.H{"error": "构建查询失败"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := esapi.SearchRequest{
|
||||||
|
Index: []string{ESIndex},
|
||||||
|
Body: bytes.NewReader(body),
|
||||||
|
TrackTotalHits: true,
|
||||||
|
Pretty: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建监控客户端并执行查询
|
||||||
|
monitoredES := monitor.NewMonitoredESClient(svc.ES.Client, endpoint)
|
||||||
|
resp, duration, err := monitoredES.Search(ctx, &req)
|
||||||
|
|
||||||
|
log.Printf("[SearchBookByISBNHandler] ES 查询耗时:%dms", duration.Milliseconds())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[SearchBookByISBNHandler] ES 查询失败:%v", err)
|
||||||
|
c.JSON(500, gin.H{"error": "ES 查询失败:" + err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.IsError() {
|
||||||
|
log.Printf("[SearchBookByISBNHandler] ES 返回错误:%s", resp.String())
|
||||||
|
c.JSON(500, gin.H{"error": "ES 返回错误:" + resp.String()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsed esHitsWrapper
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&parsed); err != nil {
|
||||||
|
log.Printf("[SearchBookByISBNHandler] 解析 ES 响应失败:%v", err)
|
||||||
|
c.JSON(500, gin.H{"error": "解析响应失败"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var result *ESBook
|
||||||
|
if len(parsed.Hits.Hits) > 0 {
|
||||||
|
result = &parsed.Hits.Hits[0].Source
|
||||||
|
}
|
||||||
|
|
||||||
|
if result == nil {
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
"data": nil,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData := result.ConvertToResponseByPsi()
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
"data": responseData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// ConvertKongfzToESBook 将第三方接口返回的数据转换为 ESBook 结构
|
// ConvertKongfzToESBook 将第三方接口返回的数据转换为 ESBook 结构
|
||||||
func ConvertKongfzToESBook(apiBook *kongfz.BookResponse) *ESBook {
|
func ConvertKongfzToESBook(apiBook *kongfz.BookResponse) *ESBook {
|
||||||
if apiBook == nil || apiBook.Data.ISBN == "" {
|
if apiBook == nil || apiBook.Data.ISBN == "" {
|
||||||
@ -3512,6 +3726,10 @@ func (svc *ESSearchService) AddBookToES(ctx context.Context, req *ESBook) (*ESBo
|
|||||||
return nil, fmt.Errorf("ES返回错误: %s", res.String())
|
return nil, fmt.Errorf("ES返回错误: %s", res.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 同步 Redis
|
||||||
|
if svc.SyncRedisByISBN != nil {
|
||||||
|
_ = svc.SyncRedisByISBN(req.ISBN, "update")
|
||||||
|
}
|
||||||
return &newBook, nil
|
return &newBook, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4152,3 +4370,77 @@ func ConvertRedisBookToESBook(redisBook *request.BookInfo) *ESBook {
|
|||||||
IsFilter: "000000",
|
IsFilter: "000000",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConvertRedisBookToESBookByPsi 将 Redis 中的 BookInfo 转换为 ESBook
|
||||||
|
func ConvertRedisBookToESBookByPsi(redisBook *request.BookInfoByPsi) *ESBook {
|
||||||
|
if redisBook == nil || redisBook.Isbn == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建图片对象
|
||||||
|
carouselUrls := []string{}
|
||||||
|
if len(redisBook.ImageObject.CarouselUrlArray) > 0 {
|
||||||
|
carouselUrls = redisBook.ImageObject.CarouselUrlArray
|
||||||
|
}
|
||||||
|
|
||||||
|
liveShootingUrls := []string{}
|
||||||
|
if len(redisBook.ImageObject.DetailUrlObject.LiveShootingUrl) > 0 {
|
||||||
|
liveShootingUrls = redisBook.ImageObject.DetailUrlObject.LiveShootingUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取第一张轮播图作为 book_pic
|
||||||
|
bookPicPath := ""
|
||||||
|
if len(carouselUrls) > 0 {
|
||||||
|
bookPicPath = carouselUrls[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取第一张实拍图作为 book_pic_s
|
||||||
|
bookPicSResponse := ""
|
||||||
|
if len(liveShootingUrls) > 0 {
|
||||||
|
bookPicSResponse = liveShootingUrls[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ESBook{
|
||||||
|
ISBN: redisBook.Isbn,
|
||||||
|
BookName: FlexibleString{Value: redisBook.BookName},
|
||||||
|
Author: redisBook.Author,
|
||||||
|
Publisher: redisBook.Publishing,
|
||||||
|
PublicationTime: redisBook.PublicationDate,
|
||||||
|
BindingLayout: redisBook.Binding,
|
||||||
|
PageCount: NumberOrString(strconv.FormatInt(redisBook.PagesCount, 10)),
|
||||||
|
WordCount: NumberOrString(strconv.FormatInt(redisBook.WordsCount, 10)),
|
||||||
|
BookFormat: NumberOrString(strconv.FormatInt(redisBook.Format, 10)),
|
||||||
|
FixPrice: Float64OrString(redisBook.Price),
|
||||||
|
BookPic: BookPicObj{
|
||||||
|
LocalPath: "",
|
||||||
|
PddPath: bookPicPath,
|
||||||
|
},
|
||||||
|
BookPicS: BookPicSObj{
|
||||||
|
LocalPath: "",
|
||||||
|
PddResponse: bookPicSResponse,
|
||||||
|
},
|
||||||
|
BookDefPic: BookDefPicObj{
|
||||||
|
LocalPath: "",
|
||||||
|
PddPath: redisBook.ImageObject.DefaultImageUrl,
|
||||||
|
},
|
||||||
|
BookPicB: redisBook.ImageObject.WhiteBackgroundUrl,
|
||||||
|
CatId: redisBook.CatIdObject,
|
||||||
|
// 销量等字段默认为 0
|
||||||
|
DaySale7: 0,
|
||||||
|
DaySale15: 0,
|
||||||
|
DaySale30: 0,
|
||||||
|
DaySale60: 0,
|
||||||
|
DaySale90: 0,
|
||||||
|
DaySale180: 0,
|
||||||
|
DaySale365: 0,
|
||||||
|
ThisYearSale: 0,
|
||||||
|
LastYearSale: 0,
|
||||||
|
TotalSale: 0,
|
||||||
|
BuyCounts: 0,
|
||||||
|
SellCounts: 0,
|
||||||
|
IsSuit: redisBook.IsSuit,
|
||||||
|
IsIllegal: 0,
|
||||||
|
IsReturn: 0,
|
||||||
|
IsFilter: "000000",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
3
main.go
3
main.go
@ -311,6 +311,8 @@ func main() {
|
|||||||
r.GET("/api/es/searchByISBNLike", esService.SearchBooksHandler) //监控
|
r.GET("/api/es/searchByISBNLike", esService.SearchBooksHandler) //监控
|
||||||
// ISBN 精确搜索
|
// ISBN 精确搜索
|
||||||
r.GET("/api/es/searchByISBN", esService.SearchBookByISBNHandler) //监控
|
r.GET("/api/es/searchByISBN", esService.SearchBookByISBNHandler) //监控
|
||||||
|
// ISBN 精确搜索 为psi提供
|
||||||
|
r.GET("/api/es/searchByISBNtoPsi", esService.SearchBookByISBNHandlerToPsi) //监控
|
||||||
// 书名搜索
|
// 书名搜索
|
||||||
r.GET("/api/es/searchByBookName", esService.SearchBookByBookNameHandler)
|
r.GET("/api/es/searchByBookName", esService.SearchBookByBookNameHandler)
|
||||||
// 全字段搜索
|
// 全字段搜索
|
||||||
@ -321,6 +323,7 @@ func main() {
|
|||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// 初始化控制器 新
|
// 初始化控制器 新
|
||||||
bookSearchService := service.NewBookService(esClient)
|
bookSearchService := service.NewBookService(esClient)
|
||||||
|
esService.SyncRedisByISBN = bookSearchService.SyncRedisByISBN
|
||||||
bookController := controller.NewBookController(bookSearchService)
|
bookController := controller.NewBookController(bookSearchService)
|
||||||
// 根据条件查询 ES 图书信息
|
// 根据条件查询 ES 图书信息
|
||||||
r.GET("/api/es/getBookBaseInfoES", bookController.SearchBookBaseInfoHandler)
|
r.GET("/api/es/getBookBaseInfoES", bookController.SearchBookBaseInfoHandler)
|
||||||
|
|||||||
@ -70,6 +70,23 @@ type BookInfo struct {
|
|||||||
CatIdObject CatIdObject `json:"cat_id"` // 分类
|
CatIdObject CatIdObject `json:"cat_id"` // 分类
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BookInfoByPsi 书籍信息结构
|
||||||
|
type BookInfoByPsi struct {
|
||||||
|
Isbn string `json:"isbn"` // ISBN
|
||||||
|
BookName string `json:"book_name"` // 书名
|
||||||
|
Author string `json:"author"` // 作者
|
||||||
|
Publishing string `json:"publishing"` // 出版社
|
||||||
|
PublicationDate string `json:"publication_date"` // 出版时间
|
||||||
|
Binding string `json:"binding"` // 装帧
|
||||||
|
PagesCount int64 `json:"pages_count"` // 页数
|
||||||
|
WordsCount int64 `json:"words_count"` // 字数
|
||||||
|
Format int64 `json:"format"` // 开本
|
||||||
|
ImageObject *ImageObject `json:"image_object"` // 图片
|
||||||
|
Price int64 `json:"price"` // 售价
|
||||||
|
CatIdObject CatIdObject `json:"cat_id"` // 分类
|
||||||
|
IsSuit int `json:"is_suit"`
|
||||||
|
}
|
||||||
|
|
||||||
// ImageObject 图片对象结构
|
// ImageObject 图片对象结构
|
||||||
type ImageObject struct {
|
type ImageObject struct {
|
||||||
CarouselUrlArray []string `json:"carousel_url_array"` // 轮播图
|
CarouselUrlArray []string `json:"carousel_url_array"` // 轮播图
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user