孔夫子分类筛选
This commit is contained in:
parent
6894d4892d
commit
ce1261dcbf
177
es/es_search.go
177
es/es_search.go
@ -1692,7 +1692,7 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 不作为查询条件的字段
|
// 不作为查询条件的字段
|
||||||
if key == "page" || key == "pageSize" || key == "per_page" || key == "saleSelect" || key == "picType" || key == "shopType" {
|
if key == "page" || key == "pageSize" || key == "per_page" || key == "saleSelect" || key == "picType" || key == "shopType" || key == "kongfz_include" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1714,7 +1714,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
|||||||
key = nk
|
key = nk
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO ===== is_suit =====
|
|
||||||
if key == "is_suit" {
|
if key == "is_suit" {
|
||||||
fmt.Printf("[DEBUG] is_suit val=%q\n", val)
|
fmt.Printf("[DEBUG] is_suit val=%q\n", val)
|
||||||
if num, err := strconv.Atoi(val); err == nil {
|
if num, err := strconv.Atoi(val); err == nil {
|
||||||
@ -1729,7 +1728,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO ===== is_return =====
|
|
||||||
if key == "is_return" {
|
if key == "is_return" {
|
||||||
fmt.Printf("[DEBUG] is_return val=%q\n", val)
|
fmt.Printf("[DEBUG] is_return val=%q\n", val)
|
||||||
if num, err := strconv.Atoi(val); err == nil {
|
if num, err := strconv.Atoi(val); err == nil {
|
||||||
@ -1744,7 +1742,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== is_filter =====
|
|
||||||
// ===== is_filter(按 shopType 位匹配)=====
|
// ===== is_filter(按 shopType 位匹配)=====
|
||||||
if key == "is_filter" {
|
if key == "is_filter" {
|
||||||
fmt.Printf("[DEBUG] is_filter val=%q\n", val)
|
fmt.Printf("[DEBUG] is_filter val=%q\n", val)
|
||||||
@ -1951,32 +1948,6 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
//if minVal == 0 {
|
|
||||||
// cond = map[string]interface{}{
|
|
||||||
// "bool": map[string]interface{}{
|
|
||||||
// "should": []map[string]interface{}{
|
|
||||||
// // 情况 1: total_sale 字段不存在或为 null
|
|
||||||
// {
|
|
||||||
// "bool": map[string]interface{}{
|
|
||||||
// "must_not": []map[string]interface{}{
|
|
||||||
// {"exists": map[string]interface{}{"field": "total_sale"}},
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// // 情况 2: total_sale 在范围内
|
|
||||||
// {
|
|
||||||
// "range": map[string]interface{}{
|
|
||||||
// "total_sale": map[string]interface{}{
|
|
||||||
// "gte": minVal,
|
|
||||||
// "lte": maxVal,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// "minimum_should_match": 1,
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
must = append(must, cond)
|
must = append(must, cond)
|
||||||
fmt.Printf("[DEBUG] must += %v\n", cond)
|
fmt.Printf("[DEBUG] must += %v\n", cond)
|
||||||
continue
|
continue
|
||||||
@ -2025,6 +1996,70 @@ func (svc *ESSearchService) BatchGetBookBaseInfoES(c *gin.Context) ([]ESBook, in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== kongfz_categories(孔夫子分类)=====
|
||||||
|
if key == "kongfz_categories" {
|
||||||
|
kongfzInclude := c.DefaultQuery("kongfz_include", "1")
|
||||||
|
|
||||||
|
// 分割多个分类ID
|
||||||
|
categories := strings.Split(val, ",")
|
||||||
|
if len(categories) > 0 {
|
||||||
|
// 过滤空值
|
||||||
|
var validCategories []string
|
||||||
|
for _, catID := range categories {
|
||||||
|
catID = strings.TrimSpace(catID)
|
||||||
|
if catID != "" {
|
||||||
|
validCategories = append(validCategories, catID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(validCategories) > 0 {
|
||||||
|
if kongfzInclude == "2" {
|
||||||
|
// 否:查询不包含这些分类的数据(must_not)
|
||||||
|
var mustNotQueries []map[string]interface{}
|
||||||
|
for _, catID := range validCategories {
|
||||||
|
mustNotQueries = append(mustNotQueries, map[string]interface{}{
|
||||||
|
"prefix": map[string]interface{}{
|
||||||
|
"cat_id.kong_fu_zi_cat_id": catID,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mustNotQueries) > 0 {
|
||||||
|
cond := map[string]interface{}{
|
||||||
|
"bool": map[string]interface{}{
|
||||||
|
"must_not": mustNotQueries,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
must = append(must, cond)
|
||||||
|
fmt.Printf("[DEBUG] must += %v (kongfz exclude: %d categories)\n", cond, len(mustNotQueries))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 是:查询包含这些分类的数据(should + minimum_should_match=1)
|
||||||
|
var shouldQueries []map[string]interface{}
|
||||||
|
for _, catID := range validCategories {
|
||||||
|
shouldQueries = append(shouldQueries, map[string]interface{}{
|
||||||
|
"prefix": map[string]interface{}{
|
||||||
|
"cat_id.kong_fu_zi_cat_id": catID,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(shouldQueries) > 0 {
|
||||||
|
cond := map[string]interface{}{
|
||||||
|
"bool": map[string]interface{}{
|
||||||
|
"should": shouldQueries,
|
||||||
|
"minimum_should_match": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
must = append(must, cond)
|
||||||
|
fmt.Printf("[DEBUG] must += %v (kongfz include: %d categories)\n", cond, len(shouldQueries))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// ===== 数值范围 =====
|
// ===== 数值范围 =====
|
||||||
if key == "sell_counts" ||
|
if key == "sell_counts" ||
|
||||||
strings.HasPrefix(key, "day_sale_") ||
|
strings.HasPrefix(key, "day_sale_") ||
|
||||||
@ -2454,6 +2489,88 @@ func (svc *ESSearchService) SearchBookByISBNHandler(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (svc *ESSearchService) SearchByISBNByXyCallBack(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()
|
||||||
|
|
||||||
|
// 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.ConvertToResponse()
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
"data": responseData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (svc *ESSearchService) SearchBookByISBNHandlerToPsi(c *gin.Context) {
|
func (svc *ESSearchService) SearchBookByISBNHandlerToPsi(c *gin.Context) {
|
||||||
isbn := c.Query("isbn")
|
isbn := c.Query("isbn")
|
||||||
if isbn == "" {
|
if isbn == "" {
|
||||||
|
|||||||
2
main.go
2
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 精确搜索 为咸鱼商品下架回调
|
||||||
|
r.GET("/api/es/searchByISBNByXyCallBack", esService.SearchByISBNByXyCallBack) //监控
|
||||||
// ISBN 精确搜索 为psi提供
|
// ISBN 精确搜索 为psi提供
|
||||||
r.GET("/api/es/searchByISBNtoPsi", esService.SearchBookByISBNHandlerToPsi) //监控
|
r.GET("/api/es/searchByISBNtoPsi", esService.SearchBookByISBNHandlerToPsi) //监控
|
||||||
// 书名搜索
|
// 书名搜索
|
||||||
|
|||||||
@ -36,6 +36,8 @@ type BookSearchRequest struct {
|
|||||||
ID string `form:"id"` // ID
|
ID string `form:"id"` // ID
|
||||||
PageCount string `form:"page_count"` // 页数
|
PageCount string `form:"page_count"` // 页数
|
||||||
WordCount string `form:"word_count"` // 字数
|
WordCount string `form:"word_count"` // 字数
|
||||||
|
KongfzCategories string `form:"kongfz_categories"` // 孔夫子分类列表,多个用逗号分隔
|
||||||
|
KongfzInclude int8 `form:"kongfz_include"` // 是否涵盖:1-是,2-否
|
||||||
}
|
}
|
||||||
|
|
||||||
// BookUpdateRequest 更新图书请求参数
|
// BookUpdateRequest 更新图书请求参数
|
||||||
|
|||||||
@ -122,6 +122,7 @@ func (svc *BookService) SearchBookBaseInfo(request *request.BookSearchRequest) (
|
|||||||
svc.buildIsFilterCondition(queryBuilder, request.IsFilter, request.ShopType)
|
svc.buildIsFilterCondition(queryBuilder, request.IsFilter, request.ShopType)
|
||||||
svc.buildCategoryTypeCondition(queryBuilder, request.CategoryType)
|
svc.buildCategoryTypeCondition(queryBuilder, request.CategoryType)
|
||||||
svc.buildCategoryCondition(queryBuilder, request.Category)
|
svc.buildCategoryCondition(queryBuilder, request.Category)
|
||||||
|
svc.buildKongfzCategoryCondition(queryBuilder, request.KongfzCategories, request.KongfzInclude)
|
||||||
svc.buildBookPicCondition(queryBuilder, request.BookPic, request.PicType)
|
svc.buildBookPicCondition(queryBuilder, request.BookPic, request.PicType)
|
||||||
svc.buildBuyCountsCondition(queryBuilder, request.BuyCounts, saleField)
|
svc.buildBuyCountsCondition(queryBuilder, request.BuyCounts, saleField)
|
||||||
svc.buildTotalSaleRangeCondition(queryBuilder, request.TotalSaleRange)
|
svc.buildTotalSaleRangeCondition(queryBuilder, request.TotalSaleRange)
|
||||||
@ -298,14 +299,10 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
|
|||||||
if isOne(isSuitValue) {
|
if isOne(isSuitValue) {
|
||||||
params["is_filter"] = "100100"
|
params["is_filter"] = "100100"
|
||||||
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_filter = params.is_filter;"))
|
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_filter = params.is_filter;"))
|
||||||
log.Printf("[UpdateBookFieldsByISBN] 检测到 is_suit=1,自动设置 is_filter=100100 | ISBN=%s | 原始类型:%T",
|
|
||||||
request.ISBN, isSuitValue)
|
|
||||||
} else {
|
} else {
|
||||||
// is_suit 不为 1 时,清空 is_filter
|
// is_suit 不为 1 时,清空 is_filter
|
||||||
params["is_filter"] = "000000"
|
params["is_filter"] = "000000"
|
||||||
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_filter = params.is_filter;"))
|
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_filter = params.is_filter;"))
|
||||||
log.Printf("[UpdateBookFieldsByISBN] 检测到 is_suit!=1,清空 is_filter | ISBN=%s | is_suit 值:%v",
|
|
||||||
request.ISBN, isSuitValue)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 未传递 is_suit,自动检测并设置
|
// 未传递 is_suit,自动检测并设置
|
||||||
@ -317,17 +314,15 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
|
|||||||
if isSuitValue == 1 {
|
if isSuitValue == 1 {
|
||||||
params["is_filter"] = "100100"
|
params["is_filter"] = "100100"
|
||||||
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_filter = params.is_filter;"))
|
scriptParts = append(scriptParts, fmt.Sprintf("ctx._source.is_filter = params.is_filter;"))
|
||||||
log.Printf("[UpdateBookFieldsByISBN] 自动检测到 is_suit=1,设置 is_filter=100100 | ISBN=%s", request.ISBN)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for field, value := range request.Data {
|
for field, value := range request.Data {
|
||||||
if field == "is_suit" {
|
if field == "is_suit" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 使用配置检查字段是否允许更新
|
// 使用配置检查字段是否允许更新
|
||||||
if !fieldConfig.IsAllowUpdate(field) {
|
if !fieldConfig.IsAllowUpdate(field) {
|
||||||
log.Printf("[UpdateBookFieldsByISBN] 字段 %s 不允许更新,已跳过", field)
|
fmt.Printf("[UpdateBookFieldsByISBN] 字段 %s 不允许更新,已跳过", field)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 对 publication_time 字段做特殊处理
|
// 对 publication_time 字段做特殊处理
|
||||||
@ -349,7 +344,6 @@ func (svc *BookService) UpdateBookFieldsByISBN(request *request.BookUpdateReques
|
|||||||
}
|
}
|
||||||
pubTime += 5364000000
|
pubTime += 5364000000
|
||||||
params[field] = strconv.FormatInt(pubTime, 10)
|
params[field] = strconv.FormatInt(pubTime, 10)
|
||||||
log.Printf("[UpdateBookFieldsByISBN] publication_time 偏移处理:%v -> %v | ISBN=%s", value, pubTime, request.ISBN)
|
|
||||||
} else {
|
} else {
|
||||||
params[field] = value
|
params[field] = value
|
||||||
}
|
}
|
||||||
@ -1514,6 +1508,74 @@ func (svc *BookService) buildDefaultPrefixConditions(builder *ESQueryBuilder, re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildKongfzCategoryCondition 构建孔夫子分类查询条件
|
||||||
|
func (svc *BookService) buildKongfzCategoryCondition(builder *ESQueryBuilder, kongfzCategories string, kongfzInclude int8) {
|
||||||
|
if kongfzCategories == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] kongfz_categories=%s, kongfz_include=%s", kongfzCategories, kongfzInclude)
|
||||||
|
|
||||||
|
// 分割多个分类ID
|
||||||
|
categories := strings.Split(kongfzCategories, ",")
|
||||||
|
if len(categories) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤空值
|
||||||
|
var validCategories []string
|
||||||
|
for _, catID := range categories {
|
||||||
|
catID = strings.TrimSpace(catID)
|
||||||
|
if catID != "" {
|
||||||
|
validCategories = append(validCategories, catID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(validCategories) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据 kongfzInclude 参数决定查询逻辑
|
||||||
|
if kongfzInclude == 2 {
|
||||||
|
// 否:查询不包含这些分类的数据(must_not)
|
||||||
|
var mustNotQueries []map[string]interface{}
|
||||||
|
for _, catID := range validCategories {
|
||||||
|
mustNotQueries = append(mustNotQueries, map[string]interface{}{
|
||||||
|
"prefix": map[string]interface{}{
|
||||||
|
"cat_id.kong_fu_zi_cat_id": catID,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mustNotQueries) > 0 {
|
||||||
|
builder.AddBoolQuery("must_not", mustNotQueries)
|
||||||
|
log.Printf("[DEBUG] Added %d kongfz category exclude queries (must_not)", len(mustNotQueries))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 是:查询包含这些分类的数据(should + minimum_should_match=1)
|
||||||
|
var shouldQueries []map[string]interface{}
|
||||||
|
for _, catID := range validCategories {
|
||||||
|
shouldQueries = append(shouldQueries, map[string]interface{}{
|
||||||
|
"prefix": map[string]interface{}{
|
||||||
|
"cat_id.kong_fu_zi_cat_id": catID,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(shouldQueries) > 0 {
|
||||||
|
// 将 should 条件包装成内层 bool 对象,作为 must 条件添加
|
||||||
|
innerBoolQuery := map[string]interface{}{
|
||||||
|
"bool": map[string]interface{}{
|
||||||
|
"should": shouldQueries,
|
||||||
|
"minimum_should_match": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
builder.AddBoolQuery("must", []map[string]interface{}{innerBoolQuery})
|
||||||
|
log.Printf("[DEBUG] Added kongfz category include query as nested bool in must (should match at least 1)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewESQueryBuilder 创建 ES 查询构建器
|
// NewESQueryBuilder 创建 ES 查询构建器
|
||||||
func NewESQueryBuilder() *ESQueryBuilder {
|
func NewESQueryBuilder() *ESQueryBuilder {
|
||||||
return &ESQueryBuilder{
|
return &ESQueryBuilder{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user