Commit 2b9184b3 by mushishixian

品牌映射

parent 5a658fa0
package common
import (
"bom_server/internal/model"
"strings"
)
//去除两端空格
func TrimBomItemSpace(bomItems []model.BomItem) (result []model.BomItem) {
for key, item := range bomItems {
bomItems[key].BrandName = strings.TrimSpace(item.BrandName)
bomItems[key].GoodsName = strings.TrimSpace(item.GoodsName)
bomItems[key].Attrs = strings.TrimSpace(item.Attrs)
bomItems[key].Encap = strings.TrimSpace(item.Encap)
}
return bomItems
}
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/gomodule/redigo/redis" "github.com/gomodule/redigo/redis"
"github.com/syyongx/php2go"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
es "gopkg.in/olivere/elastic.v5" es "gopkg.in/olivere/elastic.v5"
"regexp" "regexp"
...@@ -17,7 +18,6 @@ import ( ...@@ -17,7 +18,6 @@ import (
) )
//根据参数去匹配商品 //根据参数去匹配商品
func MatchGoodsNameByAttrs(bomItems []model.BomItem) (result []model.BomItem, err error) { func MatchGoodsNameByAttrs(bomItems []model.BomItem) (result []model.BomItem, err error) {
client, err := es.NewClient(es.SetURL(configs.ESSetting.Url)) client, err := es.NewClient(es.SetURL(configs.ESSetting.Url))
if err != nil { if err != nil {
...@@ -31,12 +31,12 @@ func MatchGoodsNameByAttrs(bomItems []model.BomItem) (result []model.BomItem, er ...@@ -31,12 +31,12 @@ func MatchGoodsNameByAttrs(bomItems []model.BomItem) (result []model.BomItem, er
for _, item := range bomItems { for _, item := range bomItems {
//如果有型号,但是型号有可能是参数,所以先去匹配下参数,有的话转成对应的型号 //如果有型号,但是型号有可能是参数,所以先去匹配下参数,有的话转成对应的型号
if item.GoodsName != "" && item.Attrs == "" { if item.GoodsName != "" && item.Attrs == "" {
search = searchAttr(item.GoodsName, item.BrandName, item.Encap, search) search = searchAttr(item, search)
searchFlag = true searchFlag = true
} }
//如果没有型号,但是有参数(参数有可能是型号),那就去匹配参数 //如果没有型号,但是有参数(参数有可能是型号),那就去匹配参数
if item.GoodsName == "" && item.Attrs != "" { if item.GoodsName == "" && item.Attrs != "" {
search = searchAttr(item.Attrs, item.BrandName, item.Encap, search) search = searchAttr(item, search)
searchFlag = true searchFlag = true
} }
} }
...@@ -56,7 +56,6 @@ func MatchGoodsNameByAttrs(bomItems []model.BomItem) (result []model.BomItem, er ...@@ -56,7 +56,6 @@ func MatchGoodsNameByAttrs(bomItems []model.BomItem) (result []model.BomItem, er
if responses.Hits != nil { if responses.Hits != nil {
for _, hit := range responses.Hits.Hits { for _, hit := range responses.Hits.Hits {
res, _ := hit.Source.MarshalJSON() res, _ := hit.Source.MarshalJSON()
//CS0805KKX7R9BB105
if bomItems[key].GoodsName == "" { if bomItems[key].GoodsName == "" {
bomItems[key].GoodsName = gjson.Get(string(res), "goods_name").String() bomItems[key].GoodsName = gjson.Get(string(res), "goods_name").String()
} }
...@@ -67,9 +66,9 @@ func MatchGoodsNameByAttrs(bomItems []model.BomItem) (result []model.BomItem, er ...@@ -67,9 +66,9 @@ func MatchGoodsNameByAttrs(bomItems []model.BomItem) (result []model.BomItem, er
return return
} }
func searchAttr(attrOrigin, brandName, encap string, search *es.MultiSearchService) (result *es.MultiSearchService) { func searchAttr(bomItem model.BomItem, search *es.MultiSearchService) (result *es.MultiSearchService) {
//先去切割参数得到参数列表 //先去切割参数得到参数列表
attrs := splitAttrs(attrOrigin) attrs := splitAttrs(bomItem.Attrs)
//当切割出来的参数大于1个的时候,就要去针对每个参数进行里面再一次提纯 //当切割出来的参数大于1个的时候,就要去针对每个参数进行里面再一次提纯
if len(attrs) > 1 { if len(attrs) > 1 {
for key, attr := range attrs { for key, attr := range attrs {
...@@ -96,37 +95,45 @@ func searchAttr(attrOrigin, brandName, encap string, search *es.MultiSearchServi ...@@ -96,37 +95,45 @@ func searchAttr(attrOrigin, brandName, encap string, search *es.MultiSearchServi
} }
} }
//单独针对封装进行转换 //单独针对封装进行转换
if encap != "" { if bomItem.Encap != "" {
//先提取出纯数字 //先提取出纯数字
numberR, _ := regexp.Compile(mapping.PureNumberRegular) numberR, _ := regexp.Compile(mapping.PureNumberRegular)
pureNumber := numberR.FindString(encap) pureNumber := numberR.FindString(bomItem.Encap)
//再去找对应属性 //再去找对应属性
attrName, _ := redis.String(gredis.HGet("sku_map2", pureNumber)) attrName, _ := redis.String(gredis.HGet("sku_map2", pureNumber))
if attrName != "" { if attrName != "" {
attrValue := attrName + "€" + pureNumber attrValue := attrName + "€" + pureNumber
attrsSlice = append(attrsSlice, attrValue) if !php2go.InArray(attrValue, attrsSlice) {
attrsSlice = append(attrsSlice, attrValue)
}
} }
} }
query := getQuery(attrsSlice) query := getQuery(attrsSlice)
if brandName != "" && len(attrsSlice) > 0 { //如果ZyBrandId不为空,则代表匹配到了映射id,可以直接用must去查询
//提取全英文,转成大写 if bomItem.ZyBrandId != "" && len(attrsSlice) > 0 {
if strings.Contains(brandName, " ") { query.Should(es.NewTermQuery("brand_name", bomItem.ZyBrandName))
//有空格隔开只取第一个 } else {
brandName = strings.Split(brandName, " ")[0] if bomItem.BrandName != "" && len(attrsSlice) > 0 {
brandName := bomItem.BrandName
//提取全英文,转成大写
if strings.Contains(brandName, " ") {
//有空格隔开只取第一个
brandName = strings.Split(brandName, " ")[0]
}
//转成全大写,因为ES存的是大写
brandName = strings.ToUpper(brandName)
//去除特殊符号和中文等等
r1, _ := regexp.Compile(`/[^A-Za-z0-9]+/`)
brandName = r1.ReplaceAllString(brandName, "")
query.Should(es.NewTermQuery("brand_name", brandName))
} }
//转成全大写,因为ES存的是大写
brandName = strings.ToUpper(brandName)
//去除特殊符号和中文等等
r1, _ := regexp.Compile(`/[^A-Za-z0-9]+/`)
brandName = r1.ReplaceAllString(brandName, "")
query.Should(es.NewTermQuery("brand_name", brandName))
} }
source := es.NewSearchSource().Query(query) source := es.NewSearchSource().Query(query)
source.Sort("_score", false) source.Sort("_score", false)
source.Sort("brand_sort", true) source.Sort("brand_sort", true)
source = source.From(0).Size(1) source = source.From(0).Size(1)
searchRequest := es.NewSearchRequest().Source(source) searchRequest := es.NewSearchRequest().Source(source)
//fmt.Println(searchRequest.Body())
return search.Add(searchRequest) return search.Add(searchRequest)
} }
...@@ -152,7 +159,6 @@ func splitAttrs(attrs string) (result []string) { ...@@ -152,7 +159,6 @@ func splitAttrs(attrs string) (result []string) {
if len(result) > 1 { if len(result) > 1 {
return return
} }
//按照分隔符切完了,再去每个去正则提取
return return
} }
......
...@@ -50,17 +50,10 @@ func BatchSaveMatchings(bomId int, matchingList []model.BomItemMatching) (err er ...@@ -50,17 +50,10 @@ func BatchSaveMatchings(bomId int, matchingList []model.BomItemMatching) (err er
} }
now := time.Now().Unix() now := time.Now().Unix()
var itemStatus int var itemStatus int
//if matching.IsBuy == 1 && matching.Price != 0 && matching.Stock != 0 {
// itemStatus = 2
// //库存为0或者价格为0,要放到待确认
//
//} else if matching.Price == 0 || matching.Stock == 0 {
// itemStatus = 4
//}
if matching.IsBuy == 1 { if matching.IsBuy == 1 {
itemStatus = 2 itemStatus = 2
}else{ } else {
itemStatus =3 itemStatus = 3
} }
err = model.Db.Table("lie_bom_item_"+tableEnd).Where("bom_item_id = ?", matching.BomItemID). err = model.Db.Table("lie_bom_item_"+tableEnd).Where("bom_item_id = ?", matching.BomItemID).
Updates(map[string]interface{}{"item_status": itemStatus, "update_time": now}).Error Updates(map[string]interface{}{"item_status": itemStatus, "update_time": now}).Error
......
package logic package logic
import "bom_server/internal/model" import (
"bom_server/configs"
"bom_server/internal/model"
"context"
"github.com/tidwall/gjson"
es "gopkg.in/olivere/elastic.v5"
"regexp"
"strings"
)
//和品牌映射有关的逻辑 //和品牌映射有关的逻辑
func GetBrandMap(bomItems []model.BomItem) (result []model.BomItem, err error) {
client, err := es.NewClient(es.SetURL(configs.ESSetting.Url))
if err != nil {
return
}
index := "stand_brand"
search := client.MultiSearch().Index(index)
for _, bomItem := range bomItems {
search = searchBrandMap(bomItem, search)
}
res, err := search.Do(context.Background())
if err != nil {
return
}
if len(res.Responses) == 0 {
return
}
//因为是多重查询,所以会有多套结果
for key, responses := range res.Responses {
//有数据进行转换
if responses.Hits != nil {
var lyBrandIds []string
for _, hit := range responses.Hits.Hits {
res, _ := hit.Source.MarshalJSON()
lyIdArray := gjson.Get(string(res), "attrs.#.attr_brand_id").Array()
for _, id := range lyIdArray {
idSlice := strings.Split(id.String(), ",")
lyBrandIds = append(lyBrandIds, idSlice...)
}
bomItems[key].ZyBrandId = hit.Id
bomItems[key].ZyBrandName = gjson.Get(string(res), "stand_zy_brand_name").String()
}
bomItems[key].LyBrandIds = lyBrandIds
}
}
result = bomItems
return
}
//根据用户输入的品牌获取映射后的品牌,没有映射的话不变,有的话变 //根据用户输入的品牌获取映射后的品牌,没有映射的话不变,有的话变
func getBrandMap(bomItems []model.BomItem) { func searchBrandMap(bomItem model.BomItem, search *es.MultiSearchService) (result *es.MultiSearchService) {
query := getBrandMapQuery(bomItem)
source := es.NewSearchSource().Query(query)
source = source.From(0).Size(1)
searchRequest := es.NewSearchRequest().Source(source)
search.Add(searchRequest)
return search
}
//获取品牌映射搜索的查询条件
func getBrandMapQuery(bomItem model.BomItem) (query *es.BoolQuery) {
var subQuery *es.TermQuery
var nestedQuery *es.NestedQuery
query = es.NewBoolQuery()
brandName := bomItem.BrandName
brandName = strings.ToUpper(brandName)
//提取出纯中文
r, _ := regexp.Compile("[\u4e00-\u9fa5]+")
chineseBrandName := r.FindString(brandName)
if chineseBrandName != "" {
query.Should(es.NewMatchQuery("brand_name_cn", chineseBrandName))
}
//提取出纯英文
re, _ := regexp.Compile("[A-Za-z0-9]+")
englishBrandName := re.FindString(brandName)
subQuery = es.NewTermQuery("attrs.attr_brand_name", englishBrandName)
nestedQuery = es.NewNestedQuery("attrs", subQuery)
query.Should(nestedQuery)
query.MinimumNumberShouldMatch(1)
return query
} }
//
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"bom_server/configs" "bom_server/configs"
"bom_server/internal/model" "bom_server/internal/model"
"encoding/json" "encoding/json"
"fmt"
"github.com/imroc/req" "github.com/imroc/req"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"strings" "strings"
...@@ -29,7 +30,7 @@ func UpdateGoodsData(goodsMapList []GoodsMap) (err error) { ...@@ -29,7 +30,7 @@ func UpdateGoodsData(goodsMapList []GoodsMap) (err error) {
goodsIds = append(goodsIds, goodsMap.GoodsId) goodsIds = append(goodsIds, goodsMap.GoodsId)
} }
goodsIdsStr := strings.Join(goodsIds, ",") goodsIdsStr := strings.Join(goodsIds, ",")
//fmt.Println(goodsIdsStr) fmt.Println(goodsIdsStr)
goodsList, err := GetGoodsInfo(goodsIdsStr) goodsList, err := GetGoodsInfo(goodsIdsStr)
if len(goodsMapList) != 0 { if len(goodsMapList) != 0 {
bomId = goodsMapList[0].BomId bomId = goodsMapList[0].BomId
...@@ -59,6 +60,7 @@ func UpdateGoodsData(goodsMapList []GoodsMap) (err error) { ...@@ -59,6 +60,7 @@ func UpdateGoodsData(goodsMapList []GoodsMap) (err error) {
} }
} }
} }
err = BatchSaveMatchings(bomId, bomMatchingList) err = BatchSaveMatchings(bomId, bomMatchingList)
if err != nil { if err != nil {
return return
...@@ -167,7 +169,7 @@ func MatchGoodsInfo(goods model.ApiGoods, goodsMap GoodsMap) (bomMatching model. ...@@ -167,7 +169,7 @@ func MatchGoodsInfo(goods model.ApiGoods, goodsMap GoodsMap) (bomMatching model.
Mpl: goods.Mpl, Mpl: goods.Mpl,
Mpq: goods.Mpq, Mpq: goods.Mpq,
Encap: goods.Encap, Encap: goods.Encap,
Status: goods.Status, Status: 1,
AddTime: int(time.Now().Unix()), AddTime: int(time.Now().Unix()),
} }
/** /**
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"math" "math"
"regexp" "regexp"
"strings" "strings"
...@@ -76,11 +77,15 @@ func SearchGoods(bomId int, bomItems []model.BomItem, deliveryType, sort int, wg ...@@ -76,11 +77,15 @@ func SearchGoods(bomId int, bomItems []model.BomItem, deliveryType, sort int, wg
if len(bomItems) == 0 { if len(bomItems) == 0 {
return return
} }
//去除首尾空格
bomItems = common.TrimBomItemSpace(bomItems)
client, err := es.NewClient(es.SetURL(configs.ESSetting.Url)) client, err := es.NewClient(es.SetURL(configs.ESSetting.Url))
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer client.Stop() defer client.Stop()
//先去查询品牌映射,有映射关系的,就用映射关系得到的brand_id进行查询
bomItems, err = GetBrandMap(bomItems)
//匹配之前,去遍历bom_item,把没有型号名称但是有参数的bom_item进行型号补充 //匹配之前,去遍历bom_item,把没有型号名称但是有参数的bom_item进行型号补充
bomItems, err = MatchGoodsNameByAttrs(bomItems) bomItems, err = MatchGoodsNameByAttrs(bomItems)
//第一次先去精确匹配 //第一次先去精确匹配
...@@ -236,7 +241,7 @@ func search(index string, bomId int, bomItems []model.BomItem, deliveryType, sor ...@@ -236,7 +241,7 @@ func search(index string, bomId int, bomItems []model.BomItem, deliveryType, sor
bom.GoodsName = bom.Attrs bom.GoodsName = bom.Attrs
} }
//构建一个goods_name对应的bomItems列表 //构建一个goods_name对应的bomItems列表
searchRequest := getSearchParams(index, bom.GoodsName, bom.BrandName, sort, bom.Number, rawSearch) searchRequest := getSearchParams(bom, sort, rawSearch)
searchFlag = true searchFlag = true
search.Add(searchRequest) search.Add(searchRequest)
} }
...@@ -281,48 +286,57 @@ func search(index string, bomId int, bomItems []model.BomItem, deliveryType, sor ...@@ -281,48 +286,57 @@ func search(index string, bomId int, bomItems []model.BomItem, deliveryType, sor
} }
//构建请求参数 //构建请求参数
func getSearchParams(index, goodsName, brandName string, sort, number int, flag bool) (searchRequest *es.SearchRequest) { func getSearchParams(bomItem model.BomItem, sort int, flag bool) (searchRequest *es.SearchRequest) {
query := getTermQuery(goodsName, brandName, sort, number, flag) query := getTermQuery(bomItem, sort, flag)
source := es.NewSearchSource().Query(query) source := es.NewSearchSource().Query(query)
if sort == 1 { if sort == 1 {
source.Sort("_score", false)
source.Sort("sort", false) source.Sort("sort", false)
source.Sort("stock", false) source.Sort("stock", false)
source.Sort("single_price", true) source.Sort("single_price", true)
} }
//要去判断sort,sort=2是按照价格排序 //要去判断sort,sort=2是按照价格排序
if sort == 2 { if sort == 2 {
source.Sort("_score", false)
source.Sort("single_price", true) source.Sort("single_price", true)
//sort=3是按照库存排序 //sort=3是按照库存排序
} else if sort == 3 { } else if sort == 3 {
source.Sort("stock_sort", false) source.Sort("_score", false)
source.Sort("stock", false) source.Sort("stock", false)
} }
source.Sort("_score", false)
source = source.From(0).Size(1) source = source.From(0).Size(1)
searchRequest = es.NewSearchRequest().Source(source) searchRequest = es.NewSearchRequest().Source(source)
fmt.Println(searchRequest.Body())
return searchRequest return searchRequest
} }
//构建term条件 //构建term条件
func getTermQuery(goodsName, brandName string, sort, number int, flag bool) (query *es.BoolQuery) { func getTermQuery(bomItem model.BomItem, sort int, flag bool) (query *es.BoolQuery) {
query = es.NewBoolQuery() query = es.NewBoolQuery()
if flag { if flag {
field := "auto_goods_name.raw" field := "auto_goods_name.raw"
replace, _ := regexp.Compile("[^A-Za-z0-9]+") replace, _ := regexp.Compile("[^A-Za-z0-9]+")
goodsName := replace.ReplaceAllString(goodsName, "") goodsName := replace.ReplaceAllString(bomItem.GoodsName, "")
goodsName = strings.ToUpper(goodsName) goodsName = strings.ToUpper(goodsName)
//搜索商品名称 //搜索商品名称
query = query.Filter(es.NewTermQuery(field, goodsName)) query = query.Filter(es.NewTermQuery(field, goodsName))
//判断是否存在brandName,存在就去搜索brandName //判断是否存在brandName并且匹配不到对应的标准品牌
if brandName != "" { if bomItem.BrandName != "" {
brandName = strings.ToUpper(brandName) bomItem.BrandName = strings.ToUpper(bomItem.BrandName)
query = query.Should(es.NewConstantScoreQuery(es.NewTermQuery("brand_name", brandName)).Boost(2)) query = query.Should(es.NewConstantScoreQuery(es.NewTermQuery("brand_name", bomItem.BrandName)).Boost(2))
} }
//搜索库存 //搜索库存
query = query.Should(es.NewConstantScoreQuery(es.NewRangeQuery("stock").Gte(number))) query = query.Should(es.NewConstantScoreQuery(es.NewRangeQuery("stock").Gte(bomItem.Number)))
} else { } else {
field := "auto_goods_name" field := "auto_goods_name"
query = query.Must(es.NewTermQuery(field, goodsName)) query = query.Must(es.NewTermQuery(field, bomItem.GoodsName))
}
//对品牌进行判断搜索,如果能匹配到对应的自营标准品牌(那么同时也有对应的联营品牌)
if bomItem.ZyBrandId != "" {
query.Should(es.NewTermQuery("brand_id", bomItem.ZyBrandId))
for _, id := range bomItem.LyBrandIds {
query.Should(es.NewTermQuery("brand_id", id))
}
} }
//按价格排序 //按价格排序
if sort == 2 { if sort == 2 {
...@@ -332,20 +346,8 @@ func getTermQuery(goodsName, brandName string, sort, number int, flag bool) (que ...@@ -332,20 +346,8 @@ func getTermQuery(goodsName, brandName string, sort, number int, flag bool) (que
if sort == 3 { if sort == 3 {
query = query.Filter(es.NewRangeQuery("stock").Gt(0)) query = query.Filter(es.NewRangeQuery("stock").Gt(0))
} }
//query = query.Filter(es.NewRangeQuery("single_price").Gt(0))
//query = query.Filter(es.NewRangeQuery("stock").Gt(0))
if configs.ApiSetting.Mode != "debug" { if configs.ApiSetting.Mode != "debug" {
query = query.Filter(es.NewTermQuery("status", 1)) query = query.Filter(es.NewTermQuery("status", 1))
} }
//query = query.Filter(es.NewRangeQuery("single_price").Gt(0))
//src, err := query.Source()
//if err != nil {
// panic(err)
//}
//data, err := json.MarshalIndent(src, "", " ")
//if err != nil {
// panic(err)
//}
//fmt.Println(string(data))
return query return query
} }
...@@ -23,9 +23,11 @@ type BomItem struct { ...@@ -23,9 +23,11 @@ type BomItem struct {
UpdateTime int `json:"update_time"` UpdateTime int `json:"update_time"`
//映射后的自营品牌id //映射后的自营品牌id
ZyBrandId int `json:"-"` ZyBrandId string `json:"-"`
//映射后的联营品牌id //映射后的联营品牌id
LyBrandId int `json:"-"` LyBrandIds []string `json:"-"`
//映射后的品牌名称(自营品牌名称)
ZyBrandName string `json:"-"`
Matching BomItemMatching `json:"matching"` Matching BomItemMatching `json:"matching"`
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment