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"` // 扩展字段,用于兼容未来新增字段
|
||||
}
|
||||
|
||||
// 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 处理可能是字符串或数组的字段
|
||||
type FlexibleString struct {
|
||||
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
|
||||
type BookPicObj struct {
|
||||
LocalPath string `json:"localPath"`
|
||||
@ -322,8 +430,10 @@ type AddBookFullRequest struct {
|
||||
}
|
||||
|
||||
type ESSearchService struct {
|
||||
ES *ESClient
|
||||
ES *ESClient
|
||||
SyncRedisByISBN func(isbn string, act string) error
|
||||
}
|
||||
|
||||
type NumberOrString string
|
||||
|
||||
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 结构
|
||||
func ConvertKongfzToESBook(apiBook *kongfz.BookResponse) *ESBook {
|
||||
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())
|
||||
}
|
||||
|
||||
// 同步 Redis
|
||||
if svc.SyncRedisByISBN != nil {
|
||||
_ = svc.SyncRedisByISBN(req.ISBN, "update")
|
||||
}
|
||||
return &newBook, nil
|
||||
}
|
||||
|
||||
@ -4152,3 +4370,77 @@ func ConvertRedisBookToESBook(redisBook *request.BookInfo) *ESBook {
|
||||
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) //监控
|
||||
// ISBN 精确搜索
|
||||
r.GET("/api/es/searchByISBN", esService.SearchBookByISBNHandler) //监控
|
||||
// ISBN 精确搜索 为psi提供
|
||||
r.GET("/api/es/searchByISBNtoPsi", esService.SearchBookByISBNHandlerToPsi) //监控
|
||||
// 书名搜索
|
||||
r.GET("/api/es/searchByBookName", esService.SearchBookByBookNameHandler)
|
||||
// 全字段搜索
|
||||
@ -321,6 +323,7 @@ func main() {
|
||||
//------------------------------------------------------------------------
|
||||
// 初始化控制器 新
|
||||
bookSearchService := service.NewBookService(esClient)
|
||||
esService.SyncRedisByISBN = bookSearchService.SyncRedisByISBN
|
||||
bookController := controller.NewBookController(bookSearchService)
|
||||
// 根据条件查询 ES 图书信息
|
||||
r.GET("/api/es/getBookBaseInfoES", bookController.SearchBookBaseInfoHandler)
|
||||
|
||||
@ -70,6 +70,23 @@ type BookInfo struct {
|
||||
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 图片对象结构
|
||||
type ImageObject struct {
|
||||
CarouselUrlArray []string `json:"carousel_url_array"` // 轮播图
|
||||
|
||||
Loading…
Reference in New Issue
Block a user